Создать фиктивный сервис (объект) Jest с одним методом, возвращающим значение
В угловом среде, как можно очень легко создать в Шутках в Передразнивала службу для объекта службы , возвращающего значение конкретного?
Словами в стиле Mockito:
// beforeEach:
// setup my Angular component with a service component myMockService
// Test 1:
// when(myMockService.doSomething()).thenReturnValue(10);
// expect(myComponent.getBalance()).toEqual( "Your balance: 10");
Я изучил документацию Jest, но не нашел очень простого подхода. Тот, что ниже, подходит, но, возможно, у вас есть лучший подход. Поскольку в Jest есть средства для имитации, я не буду использовать, например, библиотеку 'ng-mock'.
Мой упрощенный компонент Angular:
@Component({
selector: 'app-servicecounter',
templateUrl: './servicecounter.component.html'
})
export class ServicecounterComponent {
private myValue: number = 1;
constructor(private counterService: CounterService) { }
public doSomething(): void {
// ...
myValue = this.counterService.getCount();
}
}
Это упрощенная услуга:
@Injectable()
export class CounterService {
private count = 0;
constructor() { }
public getCount(): Observable<number> {
return this.count;
}
public increment(): void {
this.count++;
}
public decrement(): void {
this.count--;
}
public reset(newCount: number): void {
this.count = newCount;
}
}
Попробуйте 1: рабочее решение: с jest.genMockFromModule:
beforeEach(async () => {
mockCounterService = jest.genMockFromModule( './counterservice.service');
mockCounterService.getCount = jest.fn( () => 3);
mockCounterService.reset = jest.fn(); // it was called, I had to mock.fn it.
await TestBed.configureTestingModule({
declarations: [ServicecounterComponent],
providers: [ { provide: CounterService, useValue: mockCounterService }],
}).compileComponents();
fixture = TestBed.createComponent(ServicecounterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('shows the count', () => {
setFieldValue(fixture, 'reset-input', String(currentCount));
click(fixture, 'reset-button');
expect(mockCounterService.getCount()).toEqual( 3);
expect( mockCounterService.getCount).toBeCalled();
});
Попробуйте 1B: замените jest.genMockFromModule на jest.createMockFromModule : работает одинаково хорошо.
Попробуйте 2: заранее создайте имитацию объекта: не сработало
jest.mock( "./counterservice.service");
beforeEach(async () => {
// Create fake
mockCounterService = new CounterService();
(mockCounterService.getCount() as jest.Mock).mockReturnValue( 0);
await TestBed.configureTestingModule({
declarations: [ServicecounterComponent],
providers: [{ provide: CounterService, useValue: mockCounterService }],
}).compileComponents();
fixture = TestBed.createComponent(ServicecounterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('shows the count', () => {
// do something that will trigger the mockCountService getCount method.
expect(mockCounterService.getCount).toEqual( 0);
});
Это не работает, выдает ошибку:
> (mockCounterService.getCount() as jest.Mock).mockReturnValue( 0);
> Cannot read property 'mockReturnValue' of undefined
Попробуйте 3: с .fn(). Недостатком является то, что исходный класс может измениться, тогда объект тестирования ДОЛЖЕН измениться.
beforeEach(async () => {
mockCounterService = {
getCount: jest.fn().mockReturnValue( 0),
increment: jest.fn,
decrement: jest.fn(),
reset: jest.fn
};
await TestBed.configureTestingModule({
declarations: [ServicecounterComponent],
providers: [{ provide: CounterService, useValue: mockCounterService }],
}).compileComponents();
});
it( '... ', () => {
// ...
expect(mockCounterService.reset).toHaveBeenCalled();
});
На этот раз ошибка:
> Matcher error: received value must be a mock or spy function ...
> expect(mockCounterService.reset).toHaveBeenCalled();
Как я могу увидеть, что метод был вызван?
То же самое с конкретным аргументом?
Возможно ли получить серию возвращаемых значений?
1 ответ
Вам нужно использоватьMockBuilder
издеваться над сервисом иMockInstance
настроить его.
Также
getCount
является наблюдаемым, поэтому его макет должен возвращаться
Subject
, которым мы можем манипулировать.
// to reset MockInstance customizations after tests
MockInstance.scope();
// to use jest.fn on all mocks https://ng-mocks.sudo.eu/extra/auto-spy
beforeEach(() => ngMocks.autoSpy('jest'));
afterEach(() => ngMocks.autoSpy('reset'));
beforeEach(() => MockBuilder(ServicecounterComponent, CounterService));
it('testing', () => {
// this is our control of observable of getCount
const getCount$ = new Subject<number>();
// now we need to return it when getCount is called
const getCount = MockInstance(CounterService, 'getCount', jest.fn())
.mockReturnValue(getCount$);
// now we can use it in our test.
const fixture = MockRender(ServicecounterComponent);
ngMocks.click('.reset-button');
expect(getCount).toHaveBeenCalled();
getCount$.next(3);
expect(ngMocks.formatText(fixture)).toContain('3');
});