链式函数调用的 Jest 单元测试
Jest Unit Test for chained function calls
我为此苦苦挣扎了一段时间。单元测试的新手..我正在尝试模拟 -
的单元测试用例
fetchFooter() {
client.items().type('footer_link')
.depthParameter(10)
.toObservable()
.subscribe((response) => {
this.setState({
resFooter: response.items,
resFooterLinked: response.linkedItems,
});
});
}
客户在哪里
import { DeliveryClient } from '@kentico/kontent-delivery';
const client = new DeliveryClient({
projectId: <projectKey>,
enableAdvancedLogging: false,
});
这是我到目前为止写的,但似乎没有用。
const sample = {
items: {},
linkedItems: {}
};//this is my response object
describe("testing client", () => {
const mockClient = {
items: jest.fn().mockReturnThis(),
type: jest.fn().mockReturnThis(),
depthParameter: jest.fn().mockReturnThis(),
toObservable: jest.fn().mockReturnThis(),
subscribe: jest.fn().mockReturnThis(),
};
const mockProps = {
client: mockClient,
};
const component = mount(
<Footer mockProps={mockProps} resFooter={true} resFooterLinked={true} />
);
describe("Component", () => {
describe("#componentDidMount", () => {
it("should mount the component and set state correctly", () => {
const mockedResponse = sample;
mockClient.subscribe.mockImplementationOnce((handler) => handler(sample));
// tslint:disable-next-line: no-string-literal
component["setState"] = jest.fn();
component.instance().fetchFooter();
expect(
mockClient.items().type().depthParameter().toObservable().subscribe
).toBeCalledWith("footer_link");
// tslint:disable-next-line: no-string-literal
expect(component["setState"]).toBeCalledWith(sample);
});
});
});
});
我收到错误消息 -
expect(jest.fn()).toBeCalledWith(...expected)
Expected: "footer_link"
Number of calls: 0
也许我在这里缺少一些基础知识。我为此寻找了解决方案,但不幸的是没有找到适合我的解决方案。
有人能帮忙吗?提前致谢
如 the reference 所述,mockReturnThis
是以下的快捷方式:
jest.fn(function () {
return this;
});
它只使函数可链接,不会将参数传递给链中的下一个函数。 subscribe
不应使用 footer_link
调用,它是使用此参数调用的 type
。
没有必要让 mocked subscribe
调用处理程序,这不能保证 setState
已在其中调用。此外,setState
不是用 sample
而是另一个对象调用的。
在测试中没有必要调用expect(mockClient.items()...)
链,这只会增加调用次数。调用断言不允许确定调用方法的顺序,这可以手动确保。
由于模拟客户端对象应该可以在 config
模块模拟中访问,变量需要提升到模块范围,这允许在组件模块中模拟 client
。
链条可以像这样进行全面测试:
// module scope
jest.mock('../../config', () => ({
__esModule: true,
default: mockClient
});
const mockClient = {
items: jest.fn(),
type: jest.fn(),
...
};
...
// describe scope
let clientCalls;
beforeEach(() => {
clientCalls = [];
mockClient.items.mockImplementation(function () { clientCalls.push(1); return this });
mockClient.type.mockImplementation(function () { clientCalls.push(2); return this });
...
});
...
// test scope
component.instance().fetchFooter();
expect(clientCalls).toEqual([1,2,3,4,5]);
expect(mockClient.items).toBeCalledWith();
expect(mockClient.type).toBeCalledWith("footer_link");
...
expect(mockClient.subscribe).toBeCalledWith(expect.any(Function));
let [handler] = mockClient.subscribe.mock.calls[0];
expect(component["setState"]).not.toBeCalled();
handler();
expect(component["setState"]).toBeCalledWith({ resFooter:..., resFooterLinked:...});
我为此苦苦挣扎了一段时间。单元测试的新手..我正在尝试模拟 -
的单元测试用例fetchFooter() {
client.items().type('footer_link')
.depthParameter(10)
.toObservable()
.subscribe((response) => {
this.setState({
resFooter: response.items,
resFooterLinked: response.linkedItems,
});
});
}
客户在哪里
import { DeliveryClient } from '@kentico/kontent-delivery';
const client = new DeliveryClient({
projectId: <projectKey>,
enableAdvancedLogging: false,
});
这是我到目前为止写的,但似乎没有用。
const sample = {
items: {},
linkedItems: {}
};//this is my response object
describe("testing client", () => {
const mockClient = {
items: jest.fn().mockReturnThis(),
type: jest.fn().mockReturnThis(),
depthParameter: jest.fn().mockReturnThis(),
toObservable: jest.fn().mockReturnThis(),
subscribe: jest.fn().mockReturnThis(),
};
const mockProps = {
client: mockClient,
};
const component = mount(
<Footer mockProps={mockProps} resFooter={true} resFooterLinked={true} />
);
describe("Component", () => {
describe("#componentDidMount", () => {
it("should mount the component and set state correctly", () => {
const mockedResponse = sample;
mockClient.subscribe.mockImplementationOnce((handler) => handler(sample));
// tslint:disable-next-line: no-string-literal
component["setState"] = jest.fn();
component.instance().fetchFooter();
expect(
mockClient.items().type().depthParameter().toObservable().subscribe
).toBeCalledWith("footer_link");
// tslint:disable-next-line: no-string-literal
expect(component["setState"]).toBeCalledWith(sample);
});
});
});
});
我收到错误消息 -
expect(jest.fn()).toBeCalledWith(...expected)
Expected: "footer_link"
Number of calls: 0
也许我在这里缺少一些基础知识。我为此寻找了解决方案,但不幸的是没有找到适合我的解决方案。 有人能帮忙吗?提前致谢
如 the reference 所述,mockReturnThis
是以下的快捷方式:
jest.fn(function () {
return this;
});
它只使函数可链接,不会将参数传递给链中的下一个函数。 subscribe
不应使用 footer_link
调用,它是使用此参数调用的 type
。
没有必要让 mocked subscribe
调用处理程序,这不能保证 setState
已在其中调用。此外,setState
不是用 sample
而是另一个对象调用的。
在测试中没有必要调用expect(mockClient.items()...)
链,这只会增加调用次数。调用断言不允许确定调用方法的顺序,这可以手动确保。
由于模拟客户端对象应该可以在 config
模块模拟中访问,变量需要提升到模块范围,这允许在组件模块中模拟 client
。
链条可以像这样进行全面测试:
// module scope
jest.mock('../../config', () => ({
__esModule: true,
default: mockClient
});
const mockClient = {
items: jest.fn(),
type: jest.fn(),
...
};
...
// describe scope
let clientCalls;
beforeEach(() => {
clientCalls = [];
mockClient.items.mockImplementation(function () { clientCalls.push(1); return this });
mockClient.type.mockImplementation(function () { clientCalls.push(2); return this });
...
});
...
// test scope
component.instance().fetchFooter();
expect(clientCalls).toEqual([1,2,3,4,5]);
expect(mockClient.items).toBeCalledWith();
expect(mockClient.type).toBeCalledWith("footer_link");
...
expect(mockClient.subscribe).toBeCalledWith(expect.any(Function));
let [handler] = mockClient.subscribe.mock.calls[0];
expect(component["setState"]).not.toBeCalled();
handler();
expect(component["setState"]).toBeCalledWith({ resFooter:..., resFooterLinked:...});