我正在尝试在 Jest 中为我使用 Amazon Cognito 的 Create React App 项目编写一些单元测试。
被测代码:
const getNewCognitoUser = (username) => {
const userData = {
Username: username,
Pool: userPool,
};
return new CognitoUser(userData);
};
const setAWSCredentials = (jwt) => {
return new Promise((resolve, reject) => {
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: appConfig.IdentityPoolId,
Logins: {
[appConfig.Logins.cognito.identityProviderName]: jwt,
},
});
AWS.config.credentials.clearCachedId();
AWS.config.credentials.refresh((err) => {
err ? reject(err) : resolve();
});
});
};
export const authenticate = (username, password) => {
const authenticationDetails = new AuthenticationDetails({
Username: username,
Password: password,
});
cognitoUser = getNewCognitoUser(username);
return new Promise((resolve, reject) => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
setAWSCredentials(result.idToken.jwtToken)
.then(() => {
resolve(result);
})
.catch((err) => {
reject(err);
});
},
onFailure: function (err) {
reject(err);
},
newPasswordRequired: function (userAttributes, requiredAttributes) {
reject({
code: "PasswordResetRequiredException",
message: "New Password Required",
newPasswordRequired: true,
});
},
});
});
};
测试
import { authenticate } from "../user";
import { CognitoUser } from "amazon-cognito-identity-js";
import AWS from "aws-sdk";
jest.mock("amazon-cognito-identity-js", () => {
const mCognitoUser = {
authenticateUser: jest.fn((authenticationDetails, callbacks) => {
if (callbacks && callbacks.onSuccess) {
// Simulate a successful authentication
callbacks.onSuccess({ idToken: { jwtToken: "fakeToken" } });
}
}),
};
return {
CognitoUser: jest.fn(() => mCognitoUser),
CognitoUserPool: jest.fn(),
AuthenticationDetails: jest.fn(),
CognitoUserAttribute: jest.fn(),
};
});
jest.mock("aws-sdk", () => {
const mCognitoIdentityCredentials = jest.fn().mockImplementation(() => {
return {
clearCachedId: jest.fn(),
refresh: jest.fn(),
};
});
return {
CognitoIdentityCredentials: mCognitoIdentityCredentials,
config: {},
};
});
describe("do I understand mocks", () => {
test("let's find out", async () => {
console.log(CognitoUser);
const mCognitoUser = new CognitoUser();
console.log(mCognitoUser);
console.log(mCognitoUser.authenticateUser);
await authenticate("foo", "bar");
expect(CognitoUser.authenticate).toBeCalledTimes(1);
});
});
这告诉我,函数authenticateUser未定义,当然在尝试运行时会失败
await authenticate("foo", "bar")
声明
TypeError: cognitoUser.authenticateUser is not a function
AFAICT,代码已正确模拟,那么为什么它没有看到authenticateUser 的模拟实现?
我找到了解决方案。
该应用程序是使用 Create React App 生成的,resetMocks 的默认设置为 true,这会破坏我设置的模拟实现。我不确定为什么这是默认值,但将以下内容添加到我的 package.json 文件中解决了问题。
"jest": {
"resetMocks": false
}