我有以下内容:
import React from "react";
import Firebase from "../../Firebase";
const SignOutButton = () => (
<button type="button" onClick={() => Firebase.auth().signOut()}>
Sign Out
</button>
);
export default SignOutButton;
我要测试Firebase.auth().signOut
被称为onClick
。
我在其他地方找到了这个Firebase.auth
的模拟:
const authMock = jest.fn(() => {
return {
createUserAndRetrieveDataWithEmailAndPassword: jest.fn(() =>
Promise.resolve(true)
),
sendPasswordResetEmail: jest.fn(() => Promise.resolve(true)),
signInAndRetrieveDataWithEmailAndPassword: jest.fn(() =>
Promise.resolve(true)
),
fetchSignInMethodsForEmail: jest.fn(() => Promise.resolve(true)),
signOut: jest.fn(() => {
Promise.resolve(true);
}),
onAuthStateChanged: jest.fn(),
currentUser: {
sendEmailVerification: jest.fn(() => Promise.resolve(true))
}
};
});
export { authMock };
在SignOutButton.test中,我有:
import React from "react";
import { render, cleanup, fireEvent } from "@testing-library/react";
import SignOutButton from "../.";
import Firebase from "../../../Firebase";
import { authMock } from "../../../../setupTests";
// @ts-ignore
Firebase.auth = authMock;
describe("<SignOutButton />", () => {
afterEach(cleanup);
it("calls Firebase signOut on click", async () => {
const { getByText } = render(<SignOutButton />);
const button = getByText("Sign Out");
fireEvent.click(button);
expect(Firebase.auth().signOut).toHaveBeenCalled();
});
});
我的测试导致预期的呼叫为1但收到0。
我在做什么错了?
谢谢!
答案 0 :(得分:0)
您的测试存在以下问题:
用SignOutButton
代替Firebase.auth
方法后,应该导入authMock
组件。否则,Firebase.auth
方法是原始版本,而不是模拟版本。您可以使用console.log(Firebase.auth)
进行检查。
您应该为Firebase.auth
方法的返回值返回相同的引用。否则,断言将失败。
完整的单元测试解决方案:
SignOutButton.tsx
:
import React from 'react';
import Firebase from './firebase';
console.log(Firebase.auth);
console.log('should keep same reference to authObject:', Firebase.auth() === Firebase.auth());
const SignOutButton = () => (
<button type="button" onClick={() => Firebase.auth().signOut()}>
Sign Out
</button>
);
export default SignOutButton;
firebase.ts
:
export default {
auth() {
console.log('auth real implementation');
return this;
},
async signOut() {
console.log('signOut real implementation');
},
};
setupTests.ts
:
const authObjectMock = {
createUserAndRetrieveDataWithEmailAndPassword: jest.fn(() => Promise.resolve(true)),
sendPasswordResetEmail: jest.fn(() => Promise.resolve(true)),
signInAndRetrieveDataWithEmailAndPassword: jest.fn(() => Promise.resolve(true)),
fetchSignInMethodsForEmail: jest.fn(() => Promise.resolve(true)),
signOut: jest.fn(() => {
Promise.resolve(true);
}),
onAuthStateChanged: jest.fn(),
currentUser: {
sendEmailVerification: jest.fn(() => Promise.resolve(true)),
},
};
const authMock = jest.fn(() => authObjectMock);
export { authMock };
SignOutButton.test.tsx
:
import React from 'react';
import { render, cleanup, fireEvent } from '@testing-library/react';
import Firebase from './firebase';
import { authMock } from './setupTests';
// @ts-ignore
Firebase.auth = authMock;
describe('<SignOutButton />', () => {
afterEach(cleanup);
it('calls Firebase signOut on click', async () => {
const SignOutButton = (await import('./SignOutButton')).default;
const { getByText } = render(<SignOutButton />);
const button = getByText('Sign Out');
fireEvent.click(button);
expect(Firebase.auth().signOut).toHaveBeenCalled();
});
});
具有覆盖率报告的单元测试结果:
PASS src/stackoverflow/58562583/SignOutButton.test.tsx
<SignOutButton />
✓ calls Firebase signOut on click (76ms)
console.log src/stackoverflow/58562583/SignOutButton.tsx:382
{ [Function: mockConstructor]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockRestore: [Function],
mockReturnValueOnce: [Function],
mockResolvedValueOnce: [Function],
mockRejectedValueOnce: [Function],
mockReturnValue: [Function],
mockResolvedValue: [Function],
mockRejectedValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockName: [Function],
getMockName: [Function] }
console.log src/stackoverflow/58562583/SignOutButton.tsx:386
should keep same reference to authObject: true
-------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files | 63.64 | 100 | 36.36 | 60 | |
SignOutButton.tsx | 100 | 100 | 100 | 100 | |
firebase.ts | 25 | 100 | 0 | 25 | 3,4,7 |
setupTests.ts | 50 | 100 | 28.57 | 44.44 | 2,3,4,5,11 |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.943s