我正在尝试在集成测试中为网络获取运行Jest测试。它使用beforeEach来创建伪造的网络获取响应,并且应返回长度为2的响应。当我从以下代码中删除完成时,测试进行得很好,但是只要我使用done
作为回调和看来测试失败了,错误提示返回的长度只有1,而预期的长度应该是2。
它使用酶和完整的dom来测试3个组件的集成,当我不使用done
时,测试进行得很好,但是当我使用done
时,它通过了测试。
beforeEach(() => {
moxios.install();
moxios.stubRequest('http://jsonplaceholder.typicode.com/comments', {
status: 200,
response: [ { name: 'Fetch #1' }, { name: 'Fetch #2' } ]
});
});
afterEach(() => {
moxios.uninstall();
});
it('can fetch a list of comments and display them', (done) => {
// Attempt to render the *entire* app
const wrapped = mount(
<Root>
<App />
</Root>
);
// find the 'fetchComments' button and click it
wrapped.find('.fetch_comments').simulate('click');
// setTimeout is used because moxio introduces a little delay fetching the data.
// so setTimeout makes Jest to have a little delay so it won't throw error.
// Expect to find a list of comments!
//
setTimeout(() => {
wrapped.update();
console.log(wrapped.find('li').length);
expect(wrapped.find('li').length).toEqual(2);
wrapped.unmount();
done();
}, 3300);
});
1
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Uncaught [Error: expect(received).toEqual(expected) // deep equality
Expected: 2
Received: 1]
at reportException (/Users/dmml/Documents/Developer/reactPractice/testing/testing-stephen-grider/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
at Timeout.callback [as _onTimeout] (/Users/dmml/Documents/Developer/reactPractice/testing/testing-stephen-grider/node_modules/jsdom/lib/jsdom/browser/Window.js:680:7)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7) JestAssertionError: expect(received).toEqual(expected) // deep equality
Expected: 2
Received: 1
at toEqual (/Users/dmml/Documents/Developer/reactPractice/testing/testing-stephen-grider/src/__tests__/integrations.test.js:36:37)
at Timeout.callback [as _onTimeout] (/Users/dmml/Documents/Developer/reactPractice/testing/testing-stephen-grider/node_modules/jsdom/lib/jsdom/browser/Window.js:678:19)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7) {
matcherResult: {
actual: 1,
expected: 2,
message: [Function],
name: 'toEqual',
pass: false
}
}
● can fetch a list of comments and display them
expect(received).toEqual(expected) // deep equality
Expected: 2
Received: 1
34 | wrapped.update();
35 | console.log(wrapped.find('li').length);
> 36 | expect(wrapped.find('li').length).toEqual(2);
| ^
37 |
38 | wrapped.unmount();
39 | done();
at toEqual (src/__tests__/integrations.test.js:36:37)
at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:678:19)
Test Suites: 1 failed, 2 passed, 3 total
Tests: 1 failed, 5 passed, 6 total
Snapshots: 0 total
Time: 5.028s
Ran all test suites related to changed files.
答案 0 :(得分:0)
moxios
我从来没有取得过成功。因此,我更喜欢mock-axios-adapter。如果您使用的是thenables
,则可以在类字段中返回axios
调用并返回await
。否则,如果您使用async/await
,则可以简单地Promise.resolve()
类字段实例。另外,我尽量避免使用setTimeout
,因为它会增加总体测试运行时间。
例如(thenables
):
class Example extends Component {
state = {
data: [],
hasError: "",
isLoading: true
};
componentDidMount = () => {
window.setTimeout(() => {
this.fetchData("users");
}, 1500);
};
fetchData = url => {
return app
.get(`${url}`)
.then(res => {
this.setState({ isLoading: false, data: res.data });
})
.catch(err =>
this.setState({ isLoading: false, hasError: err.toString() })
);
}
handleClick = () => {
this.setState({ isLoading: true, data: [] }, () => {
this.fetchData("todos");
});
};
render = () => (
<div className="app-container">
{this.state.isLoading ? (
<ShowLoading />
) : this.state.hasError ? (
<ShowError error={this.state.hasError} />
) : (
<ShowData data={this.state.data} handleClick={this.handleClick} />
)}
</div>
);
}
例如(async/await
):
class Example extends Component {
state = {
data: [],
hasError: "",
isLoading: true
};
componentDidMount = () => {
window.setTimeout(() => {
this.fetchData("users");
}, 1500);
};
fetchData = async url => {
try {
const res = await app.get(`${url}`);
this.setState({ isLoading: false, data: res.data });
} catch (err) {
this.setState({ isLoading: false, hasError: err.toString() });
}
};
handleClick = () => {
this.setState({ isLoading: true, data: [] }, () => {
this.fetchData("todos");
});
};
render = () => (
<div className="app-container">
{this.state.isLoading ? (
<ShowLoading />
) : this.state.hasError ? (
<ShowError error={this.state.hasError} />
) : (
<ShowData data={this.state.data} handleClick={this.handleClick} />
)}
</div>
);
}
然后在您的测试中调用并解析fetchData
(适用于两个示例-我使用单词implementation
来指代伪造的API请求如何应与组件和integration
来指代真实的API 如何与组件进行交互-但这都是主观的:
import React from "react";
import MockAdapter from "axios-mock-adapter";
import { shallow } from "enzyme"; // I use shallow, but you can use mount
import Users from "../index.js";
import app from "../../../utils/axiosConfig";
const mockAxios = new MockAdapter(app);
const data = [
{
id: 1,
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz",
address: {
street: "Kulas Light",
suite: "Apt. 556",
city: "Gwenborough",
zipcode: "92998-3874",
geo: {
lat: "-37.3159",
lng: "81.1496"
}
},
phone: "1-770-736-8031 x56442",
website: "hildegard.org",
company: {
name: "Romaguera-Crona",
catchPhrase: "Multi-layered client-server neural-net",
bs: "harness real-time e-markets"
}
}
];
describe("App", () => {
let wrapper;
beforeEach(() => {
mockAxios.reset();
wrapper = shallow(<Users />);
});
afterAll(() => {
wrapper.unmount();
});
it("renders without errors", () => {
expect(wrapper.find("div.app-container")).toHaveLength(1);
});
it("initally shows that it's loading", () => {
expect(wrapper.state("isLoading")).toBeTruthy();
expect(wrapper.find("ShowLoading")).toHaveLength(1);
});
describe("API Implementation", () => {
it("renders data and shows an Update button", async () => {
mockAxios.onGet("users").reply(200, data);
await Promise.resolve(wrapper.instance().fetchData("users"));
expect(wrapper.state("isLoading")).toBeFalsy();
expect(
wrapper
.find("ShowData")
.dive()
.find("div.data")
).toHaveLength(1);
expect(
wrapper
.find("ShowData")
.dive()
.find("button.update")
).toHaveLength(1);
mockAxios.restore();
});
});
describe("API Integration", () => {
it("retrieves real data from API, renders data, and shows an Update button", async () => {
await Promise.resolve(wrapper.instance().fetchData("users"));
expect(wrapper.state("isLoading")).toBeFalsy();
expect(
wrapper
.find("ShowData")
.dive()
.find("div.data")
).toHaveLength(10);
expect(
wrapper
.find("ShowData")
.dive()
.find("button.update")
).toHaveLength(1);
});
});
});
运行位于Tests
旁边的Browser
标签。
工作示例(主题):
工作示例(异步/等待):