这是this one的后续问题(没有必要阅读这个问题来解答这个问题。)
以下面的React组件为例:
// ... Note that the mean subtraction is always carried
// out before scaling.
使用Jest,我们可以断言class Greeting extends React.Component {
constructor() {
fetch("https://api.domain.com/getName")
.then((response) => {
return response.text();
})
.then((name) => {
this.setState({
name: name
});
})
.catch(() => {
this.setState({
name: "<unknown>"
});
});
}
render() {
return <h1>Hello, {this.state.name}</h1>;
}
}
等于name
请求返回的某些文字:
getName
但以下情况并不合适:
test("greeting name is 'John Doe'", () => {
const fetchPromise = Promise.resolve({
text: () => Promise.resolve("John Doe")
});
global.fetch = () => fetchPromise;
const app = shallow(<Application />);
return fetchPromise.then((response) => response.text()).then(() => {
expect(app.state("name")).toEqual("John Doe");
});
});
我的意思是,我在某种程度上复制了测试文件中的实现。
我必须在测试中直接调用return fetchPromise.then((response) => response.text()).then(() => {
expect(app.state("name")).toEqual("John Doe");
});
或then()
,这感觉不对。特别是当catch()
也返回一个承诺时,我有两个链式response.text()
只是断言then()
等于name
。
我来自Angular,在那里可以调用John Doe
并在之后进行断言。
难道没有类似的方法来实现这一目标吗?或者还有另一种方法吗?
答案 0 :(得分:2)
在与同事讨论这个问题后,我会回答我自己的问题,这让我的事情变得更加清晰。也许上面的问题已经回答了我的问题,但我会用一些我能更好理解的文字给出答案。
我并没有从原始实现中调用then()
,我只是在另外的then()
链接后执行 。
另外,更好的做法是将fetch()
调用及其所有then()
和catch()
放入其自己的函数中并返回承诺,如下所示:
requestNameFromApi() {
return fetch("https://api.domain.com/getName")
.then((response) => {
return response.text();
})
.then((name) => {
this.setState({
name: name
});
})
.catch(() => {
this.setState({
name: "<unknown>"
});
});
}
测试文件:
test("greeting name is 'John Doe'", () => {
global.fetch = () => Promise.resolve({
text: () => Promise.resolve("John Doe")
});
const app = shallow(<Application />);
return app.instance().requestNameFromApi.then(() => {
expect(app.state("name")).toEqual("John Doe");
});
});
哪个更有意义。你有一个“请求函数”返回一个promise,你直接通过调用它来测试该函数的输出,并链接另一个then()
,最后调用它,以便我们可以安全地断言我们需要的东西。
如果您对在测试中返回promise的替代方法感兴趣,我们可以像这样编写上面的测试:
test("greeting name is 'John Doe'", async () => {
global.fetch = () => Promise.resolve({
text: () => Promise.resolve("John Doe")
});
await shallow(<Application />).instance().requestNameFromApi();
expect(app.state("name")).toEqual("John Doe");
});
答案 1 :(得分:1)
我的回答可能很糟糕,但我最近第一次测试了这种功能以及获取承诺。同样的方面使我感到困惑。
我认为你并没有在实现中复制代码,因为你必须推迟你的期望,直到你的mock / test-double承诺的异步部分完成为止。如果你把期望放在那个之外,那么期望将在你设置状态的存根的异步部分之前运行。
基本上你的测试double仍然是测试中的一个promise和expect子句,它依赖于那个执行的double需要在then子句中。