Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock getter parameter value of a mocked service

I've tried this SO post, but it's not my case.

I have a service (AnimationService), which is depended on another service (AnimationStateService). This AnimationStateService has a getter state, which I want to mock in my test. So my test looks like this:

animation.service.spec.ts

describe("AnimationService", () => {

let animationService: SpyObj<AnimationService>;
let animationStateService: SpyObj<AnimationStateService>;

beforeEach(() => {

    const spyAnimationStateService = createSpyObj("AnimationStateService", ["changeStatus"]);

    TestBed.configureTestingModule({
        providers: [
            AnimationService,
            {provide: AnimationStateService, useValue: spyAnimationStateService}
        ]
    });

    animationStateService = TestBed.get(AnimationStateService);
    animationService = TestBed.get(AnimationService);
});

fit("should call changeStatus if status is AnimationStatus.Stopped", () => {
    // Arrange
    // animationStateService.status.and.returnValue(AnimationStatus.Stopped); - Doesn't work
    // spyOnProperty(animationStateService, "status").and.returnValue(AnimationStatus.Stopped); - Doesn't work
    // animationStateService.status = AnimationStatus.Stopped; - Works, but with TSLint error

    // Act
    animationService.start();

    // Assert
    expect(animationStateService.changeStatus).toHaveBeenCalled();
   });
});

animation-state.service.spec.ts

@Injectable()
export class AnimationStateService {

public get status(): AnimationStatus { return this.state.animation.status; }
...
}

When I tried to mock the getter with:

animationStateService.status.and.returnValue(AnimationStatus.Stopped);

or with:

spyOnProperty(animationStateService, "status").and.returnValue(AnimationStatus.Stopped);

It doesn't worked. The getter simply doesn't returned the value I've been set.

This approach works:

animationStateService.status = AnimationStatus.Stopped;

but it gives me a TSLint error:

Cannot assign to 'status' because it is a constant or a read-only property.

So at this point I don't know, what else should I try to mock the getter properly and without errors.

like image 664
Runtime Terror Avatar asked Oct 17 '22 10:10

Runtime Terror


1 Answers

You should use spyOnProperty(obj, propertyName, accessTypeopt) → {Spy} with third accessType parameter to install a spy onto getter method.

E.g.

animation.service.ts:

import { Injectable } from '@angular/core';
import { AnimationStateService } from './animation-state.service';

@Injectable()
export class AnimationService {
  constructor(private animationStateService: AnimationStateService) {}
  start() {
    return this.animationStateService.status;
  }
}

animation-state.service.ts:

import { Injectable } from '@angular/core';

export enum AnimationStatus {
  Stopped = 'Stopped',
  Started = 'Started',
}

@Injectable()
export class AnimationStateService {
  state = {
    animation: {
      status: AnimationStatus.Started,
    },
  };
  public get status(): AnimationStatus {
    return this.state.animation.status;
  }
}

animation.service.spec.ts:

import { TestBed } from '@angular/core/testing';
import {
  AnimationStateService,
  AnimationStatus,
} from './animation-state.service';
import { AnimationService } from './animation.service';

fdescribe('53333050', () => {
  let animationStateService: AnimationStateService;
  let animationService: AnimationService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [AnimationService, AnimationStateService],
    });

    animationStateService = TestBed.get(AnimationStateService);
    animationService = TestBed.get(AnimationService);
  });

  it('should call changeStatus if status is AnimationStatus.Stopped', () => {
    // Arrange
    const statusGetterSpy = spyOnProperty(
      animationStateService,
      'status',
      'get'
    ).and.returnValue(AnimationStatus.Stopped);

    // Act
    const actual = animationService.start();
    expect(actual).toEqual(AnimationStatus.Stopped);

    // Assert
    expect(statusGetterSpy).toHaveBeenCalled();
  });
});

unit test result:

enter image description here

like image 171
slideshowp2 Avatar answered Oct 19 '22 03:10

slideshowp2