reactjs - 如何模拟 Firebase Auth 方法?(反应,测试库)
问题描述
我有以下组件:
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。
我究竟做错了什么?
谢谢!
解决方案
您的测试存在以下问题:
您应该
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
推荐阅读
- kendo-ui - Kendo Grid 验证消息位置问题
- android - 从日期选择器获取日期名称?
- python - 找不到模型 odoo v8
- java - PagedList 在使用 Room 的 Android 应用程序中不断增长但从未缩小
- java - PDFBox与java并排合并2个pdf文件
- css - Bootstrap 在 Angular 6 中无法正常工作
- c++ - C++ - 是否可以让子类按值包含包含类?
- python - 如何使用eonet api使用python获取自然灾害图像
- c# - 尽管引用了 dll,但无法使用命名空间
- java - 双重没有从一个方法传递到另一个方法