javascript - 在 vuejs 中测试 firebase 函数
问题描述
我想对我的 vue 组件进行单元测试。由于我正在使用firebase,这有点困难。
首先,我创建了一个__mocks__
文件夹来包含我所有的模拟函数。在该文件夹中,我创建了firebase.js
:
import * as firebase from 'firebase';
const onAuthStateChanged = jest.fn();
const getRedirectResult = jest.fn(() => Promise.resolve({
user: {
displayName: 'redirectResultTestDisplayName',
email: 'redirectTest@test.com',
emailVerified: true,
},
}));
const sendEmailVerification = jest.fn(() => Promise.resolve('result of sendEmailVerification'));
const sendPasswordResetEmail = jest.fn(() => Promise.resolve());
const createUserWithEmailAndPassword = jest.fn(() => {
console.log('heeeeelllo');
Promise.resolve({
user: {
displayName: 'redirectResultTestDisplayName',
email: 'redirectTest@test.com',
emailVerified: true,
},
});
});
const signInWithEmailAndPassword = jest.fn(() => Promise.resolve('result of signInWithEmailAndPassword'));
const signInWithRedirect = jest.fn(() => Promise.resolve('result of signInWithRedirect'));
const initializeApp = jest // eslint-disable-line no-unused-vars
.spyOn(firebase, 'initializeApp')
.mockImplementation(() => ({
auth: () => ({
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
currentUser: {
sendEmailVerification,
},
signInWithRedirect,
}),
}));
jest.spyOn(firebase, 'auth').mockImplementation(() => ({
onAuthStateChanged,
currentUser: {
displayName: 'testDisplayName',
email: 'test@test.com',
emailVerified: true,
},
getRedirectResult,
sendPasswordResetEmail,
}));
firebase.auth.FacebookAuthProvider = jest.fn(() => {});
firebase.auth.GoogleAuthProvider = jest.fn(() => {});
这个文件,我取自:https ://github.com/mrbenhowl/mocking-firebase-initializeApp-and-firebase-auth-using-jest
我要测试的组件称为EmailSignupLogin
. 在这种特殊情况下,我想测试registerViaEmail
- 方法:
methods: {
registerViaEmail() {
if (this.password.length > 0 && this.password === this.passwordReenter) {
firebase.auth().createUserWithEmailAndPassword(this.emailAdress, this.password).then((result) => {
const { user } = result;
console.log(result);
this.setUser(user);
this.$router.push('/stocks');
}).catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
this.error = errorMessage;
console.error(errorCode, errorMessage);
});
} else {
this.error = 'passwords not matching';
}
},
},
现在到我的测试文件(email-signup-login.spec.js
):
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import EmailSignupLogin from '@/components/email-signup-login';
jest.mock('../../__mocks__/firebase');
describe('EmailSignupLogin', () => {
let wrapper;
const mockFunction = jest.fn();
beforeEach(() => {
wrapper = mount(EmailSignupLogin, {
data() {
return {
password: '123456',
passwordReenter: '123456',
emailAdress: 'test@test.com',
};
},
store: {
actions: {
setUser: mockFunction,
},
},
});
});
describe('methods', () => {
describe('#registerViaEmail', () => {
it('calls mockFunction', async () => {
await wrapper.vm.registerViaEmail();
expect(mockFunction).toHaveBeenCalled();
});
});
});
});
在registerViaEmail
-method 内部我称之为setUser
-action,它是一个 vuex-action。
问题是它似乎没有从__mocks__/firebase.js
. 有人可以告诉我为什么吗?
解决方案
您的代码中出现了几个问题:
registerViaEmail()
不是async
(不返回 aPromise
),因此await
调用过早返回,此时您的测试会尝试断言尚未发生的事情。要解决这个问题,只需用一个包裹函数体Promise
:
registerViaEmail() {
return new Promise((resolve, reject) => {
if (this.password.length > 0 && this.password === this.passwordReenter) {
firebase.auth().createUserWithEmailAndPassword(this.emailAdress, this.password).then((result) => {
//...
resolve()
}).catch((error) => {
//...
reject()
});
} else {
//...
reject()
}
})
},
- 您提到的脚本不打算与 Jest 一起使用
__mocks__
。脚本本身直接修改firebase
对象,用模拟替换其方法/属性。要使用该脚本,您只需在导入使用的测试模块之前导入它firebase
:
import './firebase-mock' // <-- order important
import EmailSignupLogin from '@/components/EmailSignupLogin'
createUserWithEmailAndPassword
不返回任何东西。看起来它最初返回了Promise
,但是您使用 a 对其进行了修改console.log
,并且忘记继续返回Promise
,这导致该方法无法被await
编辑(与 #1 相同的问题)。解决方案是返回Promise
:
const createUserWithEmailAndPassword = jest.fn(() => {
console.log('heeeeelllo')
return /**/ Promise.resolve(/*...*/)
})
createUserWithEmailAndPassword
是要在 中测试的方法EmailSignupLogin
,但它目前没有在您的auth
模拟对象中模拟。它只是在 return 中被嘲笑initializeApp.auth
,但这不是它在EmailSignupLogin
. 要解决此问题,请复制createUserWithEmailAndPassword
到您的auth
模拟对象:
jest.spyOn(firebase, 'auth').mockImplementation(() => ({
onAuthStateChanged,
currentUser: {
displayName: 'testDisplayName',
email: 'test@test.com',
emailVerified: true,
},
getRedirectResult,
sendPasswordResetEmail,
createUserWithEmailAndPassword, //
}));
- 在您的测试设置中,您使用普通对象模拟了商店,但它实际上需要是以下实例
Vuex.Store
:
mount({
//store: { /*...*/ }, //❌DON'T DO THIS
store: new Vuex.Store({ /*...*/ }) //✅
})
推荐阅读
- android - 升级到 Gradle 3 后应用消失
- c# - 如何在 angular2+ 中序列化/反序列化 .NET 类型的 JSON
- elasticsearch - java.lang.IllegalStateException:可用处理器值 [3] 与当前值 [1] 不匹配
- javascript - 在运行时读取 VSTS 发布变量(TypeScript/Webpack SPA)
- tensorflow - TensorFlow shuffle 迭代器
- java - 正则表达式验证 3 个重复字符
- delphi - 如何删除加速键热键'&'字符?
- sql-server-2008 - 数据库恢复后 SSRS 登录失败
- c++ - 按升序/降序打印二项式堆的内容
- ansible - Ansible 检查主机在线 -> 如果不在线 -> 启动安装程序