在 Jest 中,我如何对订阅可观察对象的方法进行单元测试
In Jest, how can I unit test a method that subscribes to an observable
我的组件中有各种方法订阅注入依赖项中的方法,即 return 可观察对象。
我想编写 Jest 单元测试以确保当这些可观察值 return / 错误时,我的方法做正确的事情。
在下面的示例中,我尝试编写一个测试来检查 doAThing
是否已触发。以下测试均无效。他们都失败并出现
之类的错误
'returnMyObservable.subscribe is not a function'.
// Example method to test component
public testFunction (): void {
this.myService.returnMyObservable.subscribe(
( value ) => this.doAThing( value )
)
}
describe( 'myComponemt', () => {
let fixture;
let myServiceMock;
beforeEach( () => {
myServiceMock = {
returnMyObservable: fn()
}
fixture = new myComponent( myServiceMock );
});
// 1) I have tried mocking with a returned value
it ( 'should call do a thing when value is returned', () => {
myServiceMock.returnMyOnservable.mockReturnValue( true );
fixture.testFunction();
expect( fixture.doAThing ).toHaveBeenCalled();
});
// 2) I have tried returning an observable
it ( 'should call do a thing when value is returned', () => {
myServiceMock.returnMyOnservable.mockReturnValue( of( true ) );
fixture.testFunction();
expect( fixture.doAThing ).toHaveBeenCalled();
});
});
我们可以使用mockImplementation
来模拟this.myService.returnMyObservable
的实现。之后我们可以在测试用例(observer
)中获取到你在subscribe
中传入的函数,然后手动执行
解决方法如下:
index.ts
:
export class MyComponent {
private myService;
constructor(myService) {
this.myService = myService;
}
public testFunction(): void {
this.myService.returnMyObservable.subscribe(value => this.doAThing(value));
}
public doAThing(value) {}
}
index.spec.ts
:
import { MyComponent } from './';
describe('MyComponent', () => {
let fixture;
let myServiceMock;
beforeEach(() => {
myServiceMock = {
returnMyObservable: {
subscribe: jest.fn()
}
};
fixture = new MyComponent(myServiceMock);
});
it('should call do a thing when value is returned', () => {
let observer;
myServiceMock.returnMyObservable.subscribe.mockImplementation(handler => {
observer = handler;
});
jest.spyOn(fixture, 'doAThing');
fixture.testFunction();
observer();
expect(fixture.doAThing).toHaveBeenCalled();
});
});
100% 覆盖率的单元测试结果:
PASS src/Whosebug/58815471/index.spec.ts (7.367s)
MyComponent
✓ should call do a thing when value is returned (5ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.773s
源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/Whosebug/58815471
我还有其他一些错误,这些错误掩盖了我的测试中的实际错误 - 我发现测试上述功能的最佳方法是:
describe( 'MyComponent', () => {
let fixture;
let myServiceMock;
beforeEach( () => {
myServiceMock = {
returnMyObservable: jest.fn()
}
fixture = new MyComponent( myServiceMock );
});
it ( 'should call doAThing when value is returned', () => {
const doAThingSpy = jest.spyOn( fixture, 'doAThing' );
myServiceMock.returnMyObservable.mockReturnValue( of( true ) );
fixture.testFunction();
expect( doAThingSpy ).toHaveBeenCalledWith( true );
});
});
(这与在 Jasmine 中的做法几乎相同)
我的组件中有各种方法订阅注入依赖项中的方法,即 return 可观察对象。
我想编写 Jest 单元测试以确保当这些可观察值 return / 错误时,我的方法做正确的事情。
在下面的示例中,我尝试编写一个测试来检查 doAThing
是否已触发。以下测试均无效。他们都失败并出现
'returnMyObservable.subscribe is not a function'.
// Example method to test component
public testFunction (): void {
this.myService.returnMyObservable.subscribe(
( value ) => this.doAThing( value )
)
}
describe( 'myComponemt', () => {
let fixture;
let myServiceMock;
beforeEach( () => {
myServiceMock = {
returnMyObservable: fn()
}
fixture = new myComponent( myServiceMock );
});
// 1) I have tried mocking with a returned value
it ( 'should call do a thing when value is returned', () => {
myServiceMock.returnMyOnservable.mockReturnValue( true );
fixture.testFunction();
expect( fixture.doAThing ).toHaveBeenCalled();
});
// 2) I have tried returning an observable
it ( 'should call do a thing when value is returned', () => {
myServiceMock.returnMyOnservable.mockReturnValue( of( true ) );
fixture.testFunction();
expect( fixture.doAThing ).toHaveBeenCalled();
});
});
我们可以使用mockImplementation
来模拟this.myService.returnMyObservable
的实现。之后我们可以在测试用例(observer
)中获取到你在subscribe
中传入的函数,然后手动执行
解决方法如下:
index.ts
:
export class MyComponent {
private myService;
constructor(myService) {
this.myService = myService;
}
public testFunction(): void {
this.myService.returnMyObservable.subscribe(value => this.doAThing(value));
}
public doAThing(value) {}
}
index.spec.ts
:
import { MyComponent } from './';
describe('MyComponent', () => {
let fixture;
let myServiceMock;
beforeEach(() => {
myServiceMock = {
returnMyObservable: {
subscribe: jest.fn()
}
};
fixture = new MyComponent(myServiceMock);
});
it('should call do a thing when value is returned', () => {
let observer;
myServiceMock.returnMyObservable.subscribe.mockImplementation(handler => {
observer = handler;
});
jest.spyOn(fixture, 'doAThing');
fixture.testFunction();
observer();
expect(fixture.doAThing).toHaveBeenCalled();
});
});
100% 覆盖率的单元测试结果:
PASS src/Whosebug/58815471/index.spec.ts (7.367s)
MyComponent
✓ should call do a thing when value is returned (5ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.773s
源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/Whosebug/58815471
我还有其他一些错误,这些错误掩盖了我的测试中的实际错误 - 我发现测试上述功能的最佳方法是:
describe( 'MyComponent', () => {
let fixture;
let myServiceMock;
beforeEach( () => {
myServiceMock = {
returnMyObservable: jest.fn()
}
fixture = new MyComponent( myServiceMock );
});
it ( 'should call doAThing when value is returned', () => {
const doAThingSpy = jest.spyOn( fixture, 'doAThing' );
myServiceMock.returnMyObservable.mockReturnValue( of( true ) );
fixture.testFunction();
expect( doAThingSpy ).toHaveBeenCalledWith( true );
});
});
(这与在 Jasmine 中的做法几乎相同)