是否可以在节点中为没有 catch 块的承诺编写一个笑话单元测试?
Is it possible to write a jest unit test in node for a promise with no catch block?
有什么问题
我正在尝试编写一个带有用户登录的基本 React Django 样板文件。我正在使用 react-saga
.
处理登录流程
我有一个调用登录函数的 saga,它会 ping 服务器并获取令牌。 saga 处理所有的错误处理。如果该调用失败,错误将成功返回以做出反应并显示给用户。它工作正常。
我正在尝试为登录功能编写单元测试。我认为节点正在捕获我的错误:UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
我猜是因为 saga 在现实中捕获了它,所以 node 不会抛出该错误。
这是否意味着我无法对登录函数抛出未捕获的错误进行单元测试?
我不应该费心测试这个吗?
代码
这是调用服务器的函数。
# Auth login function
login(email, password) {
// If user is already logged in return true.
if (auth.loggedIn()) return Promise.resolve(true);
const credentials = btoa(`${email}:${password}`);
// Request to login
return axios({
method: "post",
url: `${SERVER_URL}/api/v1/accounts/login/`,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Basic ${credentials}`
}
}).then(response => {
// Save token to local storage
if (response.data.token) {
localStorage.auth_token = response.data.token;
} else {
// To Do-- throw error if server fails to return one
}
return Promise.resolve(true);
});
}
那么这就是处理逻辑的传奇。
export function* authorize({
email,
password,
isRegistering,
firstName,
lastName
}) {
// We send an action that tells Redux we're sending a request
yield put({ type: SENDING_REQUEST, sending: true });
// We then try to register or log in the user, depending on the request
try {
let response;
// For either log in or registering, we call the proper function in the `auth`
// module, which is asynchronous. Because we're using generators, we can work
// as if it's synchronous because we pause execution until the call is done
// with `yield`!
if (isRegistering) {
response = yield call(
register,
email,
password,
firstName,
lastName
);
} else {
response = yield call(login, email, password);
}
return response;
} catch (error) {
// If we get an error we send Redux the appropriate action and return
yield put({
type: REQUEST_ERROR,
error: error.response.data,
sending: false
});
return false;
} finally {
// When done, we tell Redux we're not in the middle of a request any more
yield put({ type: SENDING_REQUEST, sending: false });
}
}
那么这是我的单元测试:
describe("login function", () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
localStorage.clear();
});
afterEach(() => {
// We need to clear mocks
// and remove tokens from local storage to prevent
// us from staying logged in
mock.restore();
});
test("Check that exception thrown on server error", () => {
// Mock loggedin function to throw error
mock.onPost().reply(500);
Test that error is uncaught.
expect(() => {
auth.login("test@example.com", "pass").then(value => {
console.log(value);
});
}).toThrow();
});
});
你可以测试一下。 toThrow
方法用于捕获抛出的错误,但 promise 拒绝错误因此需要使用不同的 API。要捕获您的错误 .rejects.toThrow();
,您应该 await
完成 expect 块,从而导致:
describe("login function", () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
localStorage.clear();
});
afterEach(() => {
// We need to clear mocks
// and remove tokens from local storage to prevent
// us from staying logged in
mock.restore();
});
test("Check that exception thrown on server error", async () => {
// Mock loggedin function to throw error
mock.onPost().reply(500);
Test that error is uncaught.
await expect(() => auth.login("test@example.com", "pass")).rejects.toThrow(); // add an error message to check for correct error
});
});
PS。这在 jest API docs.
中有详细记录
有什么问题
我正在尝试编写一个带有用户登录的基本 React Django 样板文件。我正在使用 react-saga
.
我有一个调用登录函数的 saga,它会 ping 服务器并获取令牌。 saga 处理所有的错误处理。如果该调用失败,错误将成功返回以做出反应并显示给用户。它工作正常。
我正在尝试为登录功能编写单元测试。我认为节点正在捕获我的错误:UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
我猜是因为 saga 在现实中捕获了它,所以 node 不会抛出该错误。
这是否意味着我无法对登录函数抛出未捕获的错误进行单元测试?
我不应该费心测试这个吗?
代码
这是调用服务器的函数。
# Auth login function
login(email, password) {
// If user is already logged in return true.
if (auth.loggedIn()) return Promise.resolve(true);
const credentials = btoa(`${email}:${password}`);
// Request to login
return axios({
method: "post",
url: `${SERVER_URL}/api/v1/accounts/login/`,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Basic ${credentials}`
}
}).then(response => {
// Save token to local storage
if (response.data.token) {
localStorage.auth_token = response.data.token;
} else {
// To Do-- throw error if server fails to return one
}
return Promise.resolve(true);
});
}
那么这就是处理逻辑的传奇。
export function* authorize({
email,
password,
isRegistering,
firstName,
lastName
}) {
// We send an action that tells Redux we're sending a request
yield put({ type: SENDING_REQUEST, sending: true });
// We then try to register or log in the user, depending on the request
try {
let response;
// For either log in or registering, we call the proper function in the `auth`
// module, which is asynchronous. Because we're using generators, we can work
// as if it's synchronous because we pause execution until the call is done
// with `yield`!
if (isRegistering) {
response = yield call(
register,
email,
password,
firstName,
lastName
);
} else {
response = yield call(login, email, password);
}
return response;
} catch (error) {
// If we get an error we send Redux the appropriate action and return
yield put({
type: REQUEST_ERROR,
error: error.response.data,
sending: false
});
return false;
} finally {
// When done, we tell Redux we're not in the middle of a request any more
yield put({ type: SENDING_REQUEST, sending: false });
}
}
那么这是我的单元测试:
describe("login function", () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
localStorage.clear();
});
afterEach(() => {
// We need to clear mocks
// and remove tokens from local storage to prevent
// us from staying logged in
mock.restore();
});
test("Check that exception thrown on server error", () => {
// Mock loggedin function to throw error
mock.onPost().reply(500);
Test that error is uncaught.
expect(() => {
auth.login("test@example.com", "pass").then(value => {
console.log(value);
});
}).toThrow();
});
});
你可以测试一下。 toThrow
方法用于捕获抛出的错误,但 promise 拒绝错误因此需要使用不同的 API。要捕获您的错误 .rejects.toThrow();
,您应该 await
完成 expect 块,从而导致:
describe("login function", () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
localStorage.clear();
});
afterEach(() => {
// We need to clear mocks
// and remove tokens from local storage to prevent
// us from staying logged in
mock.restore();
});
test("Check that exception thrown on server error", async () => {
// Mock loggedin function to throw error
mock.onPost().reply(500);
Test that error is uncaught.
await expect(() => auth.login("test@example.com", "pass")).rejects.toThrow(); // add an error message to check for correct error
});
});
PS。这在 jest API docs.
中有详细记录