有没有办法开玩笑地模拟 firebase 模块?
Is there a way to mock firebase modules in jest?
Code.js
saveToFirebase = () => {
let statusMsg = ""
firebase
.firestore()
.collection("messages")
.doc(this.state.field.email)
.set(this.state.field)
.then((statusMsg = "Your Message have been submitted successfully."))
this.clearFields(statusMsg)
}
Code.test.js
it("should call mock firebase module", () => {
const docData = {
field: {
name: "Rob Bob",
email: "rob@bob.com",
phone: "9999999999",
subject: "Test subject",
message: "Test message",
},
}
const docResult = {
data: () => docData,
}
const get = jest.fn(() => Promise.resolve(docResult))
const set = jest.fn()
const doc = jest.fn(() => {
return {
set,
get,
}
})
const colllection = jest.fn((messages) => {
return { doc }
})
const firestore = () => {
return colllection
}
firebase.firestore = firestore
const mockData = { fake: "data" }
jest.clearAllMocks()
wrapper.instance().saveToFirebase()
})
虽然运行 Code.test.js,但它抛出一个错误,即firebase.firestore().collection() 不是一个函数。请建议对上述代码的 firebase 模块进行适当的模拟,并添加一个案例以检查 firebase 是否已成功返回,然后调用 clearFields()。
您可以使用 jest.spyOn(object, methodName) 模拟 firebase.firestore()
函数。
例如
index.jsx
:
import React, { Component } from 'react';
import firebase from 'firebase';
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
field: { email: 'fuck@qq.com' },
};
}
clearFields(statusMsg) {
console.log(statusMsg);
}
saveToFirebase = () => {
let statusMsg = '';
return firebase
.firestore()
.collection('messages')
.doc(this.state.field.email)
.set(this.state.field)
.then(() => {
statusMsg = 'Your Message have been submitted successfully.';
this.clearFields(statusMsg);
});
};
render() {
return <div>my component</div>;
}
}
index.test.jsx
:
import MyComponent from '.';
import { shallow } from 'enzyme';
import React from 'react';
import firebase from 'firebase';
describe('61358076', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should pass', async () => {
const firestoreMock = {
collection: jest.fn().mockReturnThis(),
doc: jest.fn().mockReturnThis(),
set: jest.fn().mockResolvedValueOnce(),
};
const clearFieldsSpy = jest.spyOn(MyComponent.prototype, 'clearFields');
jest.spyOn(firebase, 'firestore').mockImplementationOnce(() => firestoreMock);
const wrapper = shallow(<MyComponent></MyComponent>);
await wrapper.instance().saveToFirebase();
expect(firestoreMock.collection).toBeCalledWith('messages');
expect(firestoreMock.doc).toBeCalledWith('fuck@qq.com');
expect(firestoreMock.set).toBeCalledWith({ email: 'fuck@qq.com' });
expect(clearFieldsSpy).toBeCalledWith('Your Message have been submitted successfully.');
});
});
100% 覆盖率的单元测试结果:
PASS Whosebug/61358076/index.test.jsx (17.824s)
61358076
✓ should pass (39ms)
console.log Whosebug/61358076/index.jsx:1611
Your Message have been submitted successfully.
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.jsx | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 19.945s
源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/Whosebug/61358076
嗨,最近我需要模拟 jest 模块,这是我的实现,
注意:我使用 eventEmitter3 来处理 onAuthStateChange
import EventEmitter from 'eventemitter3';
const authEmitter = new EventEmitter();
let isSignIn = true;
const user = {
displayName: 'test name',
email: 'redirectTest@test.com',
emailVerified: true,
uid: 'id123',
providerData: [
{
email: 'redirectTest@test.com',
displayName: 'redirectResultTestDisplayName',
providerId: 'google',
},
],
};
const mockFirebase: any = {
initializeApp: jest.fn().mockReturnValue({
auth: jest.fn().mockReturnValue({
currentUser: isSignIn
? {
displayName: 'redirectResultTestDisplayName',
email: 'redirectTest@test.com',
emailVerified: true,
uid: 'id123',
providerData: [
{
email: 'redirectTest@test.com',
displayName: 'redirectResultTestDisplayName',
providerId: 'google',
},
],
sendEmailVerification: jest.fn(),
}
: null,
signInWithRedirect: jest.fn(),
getRedirectResult: jest.fn().mockReturnValue({
credential: {
providerId: 'Google',
},
user: {
getIdToken: jest.fn().mockResolvedValue('abc1234'),
},
additionalUserInfo: {
profile: {
email: '__tests__@__tests__.com',
name: 'John Doe',
},
},
}),
onAuthStateChanged: jest.fn(fn => {
// sign user on start
fn(user);
// sign-out user on start
authEmitter.on('sign-out', fn, undefined);
authEmitter.on('sign-in', fn, user);
}),
signOut: jest.fn(() => {
isSignIn = false;
authEmitter.emit('sign-out');
}),
signInWithEmailAndPassword: jest.fn(() => {
isSignIn = true;
authEmitter.emit('sign-in', user);
return Promise.resolve(true);
}),
sendPasswordResetEmail: jest.fn(() => Promise.resolve(true)),
sendEmailVerification: jest.fn(() => Promise.resolve(true)),
signInWithPopup: jest.fn(() => {
isSignIn = true;
authEmitter.emit('sign-in', user);
return Promise.resolve(true);
}),
}),
firestore: jest.fn().mockReturnValue({
collection: jest.fn().mockReturnValue({
doc: jest.fn().mockReturnValue({
add: jest.fn().mockResolvedValue({
id: 'abc123',
}),
set: jest.fn().mockResolvedValue({
uid: 'abc123',
}),
}),
}),
}),
}),
auth: {
GoogleAuthProvider: class {
addScope = jest.fn();
},
GithubAuthProvider: class {
addScope = jest.fn();
},
FacebookAuthProvider: class {
addScope = jest.fn();
},
},
};
jest.mock('firebase/app', () => mockFirebase);
Code.js
saveToFirebase = () => {
let statusMsg = ""
firebase
.firestore()
.collection("messages")
.doc(this.state.field.email)
.set(this.state.field)
.then((statusMsg = "Your Message have been submitted successfully."))
this.clearFields(statusMsg)
}
Code.test.js
it("should call mock firebase module", () => {
const docData = {
field: {
name: "Rob Bob",
email: "rob@bob.com",
phone: "9999999999",
subject: "Test subject",
message: "Test message",
},
}
const docResult = {
data: () => docData,
}
const get = jest.fn(() => Promise.resolve(docResult))
const set = jest.fn()
const doc = jest.fn(() => {
return {
set,
get,
}
})
const colllection = jest.fn((messages) => {
return { doc }
})
const firestore = () => {
return colllection
}
firebase.firestore = firestore
const mockData = { fake: "data" }
jest.clearAllMocks()
wrapper.instance().saveToFirebase()
})
虽然运行 Code.test.js,但它抛出一个错误,即firebase.firestore().collection() 不是一个函数。请建议对上述代码的 firebase 模块进行适当的模拟,并添加一个案例以检查 firebase 是否已成功返回,然后调用 clearFields()。
您可以使用 jest.spyOn(object, methodName) 模拟 firebase.firestore()
函数。
例如
index.jsx
:
import React, { Component } from 'react';
import firebase from 'firebase';
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
field: { email: 'fuck@qq.com' },
};
}
clearFields(statusMsg) {
console.log(statusMsg);
}
saveToFirebase = () => {
let statusMsg = '';
return firebase
.firestore()
.collection('messages')
.doc(this.state.field.email)
.set(this.state.field)
.then(() => {
statusMsg = 'Your Message have been submitted successfully.';
this.clearFields(statusMsg);
});
};
render() {
return <div>my component</div>;
}
}
index.test.jsx
:
import MyComponent from '.';
import { shallow } from 'enzyme';
import React from 'react';
import firebase from 'firebase';
describe('61358076', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should pass', async () => {
const firestoreMock = {
collection: jest.fn().mockReturnThis(),
doc: jest.fn().mockReturnThis(),
set: jest.fn().mockResolvedValueOnce(),
};
const clearFieldsSpy = jest.spyOn(MyComponent.prototype, 'clearFields');
jest.spyOn(firebase, 'firestore').mockImplementationOnce(() => firestoreMock);
const wrapper = shallow(<MyComponent></MyComponent>);
await wrapper.instance().saveToFirebase();
expect(firestoreMock.collection).toBeCalledWith('messages');
expect(firestoreMock.doc).toBeCalledWith('fuck@qq.com');
expect(firestoreMock.set).toBeCalledWith({ email: 'fuck@qq.com' });
expect(clearFieldsSpy).toBeCalledWith('Your Message have been submitted successfully.');
});
});
100% 覆盖率的单元测试结果:
PASS Whosebug/61358076/index.test.jsx (17.824s)
61358076
✓ should pass (39ms)
console.log Whosebug/61358076/index.jsx:1611
Your Message have been submitted successfully.
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.jsx | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 19.945s
源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/Whosebug/61358076
嗨,最近我需要模拟 jest 模块,这是我的实现, 注意:我使用 eventEmitter3 来处理 onAuthStateChange
import EventEmitter from 'eventemitter3';
const authEmitter = new EventEmitter();
let isSignIn = true;
const user = {
displayName: 'test name',
email: 'redirectTest@test.com',
emailVerified: true,
uid: 'id123',
providerData: [
{
email: 'redirectTest@test.com',
displayName: 'redirectResultTestDisplayName',
providerId: 'google',
},
],
};
const mockFirebase: any = {
initializeApp: jest.fn().mockReturnValue({
auth: jest.fn().mockReturnValue({
currentUser: isSignIn
? {
displayName: 'redirectResultTestDisplayName',
email: 'redirectTest@test.com',
emailVerified: true,
uid: 'id123',
providerData: [
{
email: 'redirectTest@test.com',
displayName: 'redirectResultTestDisplayName',
providerId: 'google',
},
],
sendEmailVerification: jest.fn(),
}
: null,
signInWithRedirect: jest.fn(),
getRedirectResult: jest.fn().mockReturnValue({
credential: {
providerId: 'Google',
},
user: {
getIdToken: jest.fn().mockResolvedValue('abc1234'),
},
additionalUserInfo: {
profile: {
email: '__tests__@__tests__.com',
name: 'John Doe',
},
},
}),
onAuthStateChanged: jest.fn(fn => {
// sign user on start
fn(user);
// sign-out user on start
authEmitter.on('sign-out', fn, undefined);
authEmitter.on('sign-in', fn, user);
}),
signOut: jest.fn(() => {
isSignIn = false;
authEmitter.emit('sign-out');
}),
signInWithEmailAndPassword: jest.fn(() => {
isSignIn = true;
authEmitter.emit('sign-in', user);
return Promise.resolve(true);
}),
sendPasswordResetEmail: jest.fn(() => Promise.resolve(true)),
sendEmailVerification: jest.fn(() => Promise.resolve(true)),
signInWithPopup: jest.fn(() => {
isSignIn = true;
authEmitter.emit('sign-in', user);
return Promise.resolve(true);
}),
}),
firestore: jest.fn().mockReturnValue({
collection: jest.fn().mockReturnValue({
doc: jest.fn().mockReturnValue({
add: jest.fn().mockResolvedValue({
id: 'abc123',
}),
set: jest.fn().mockResolvedValue({
uid: 'abc123',
}),
}),
}),
}),
}),
auth: {
GoogleAuthProvider: class {
addScope = jest.fn();
},
GithubAuthProvider: class {
addScope = jest.fn();
},
FacebookAuthProvider: class {
addScope = jest.fn();
},
},
};
jest.mock('firebase/app', () => mockFirebase);