快照测试使用 firebase 函数的组件 - 开玩笑的模拟
Snapshot testing a component that uses firebase functions - Mock in jest
我在 React Native 项目中工作,我想用 Jest 对我的 LoginComponent 进行快照测试。
LoginComponent.js 在这里看到,我正在使用 firebase 的一些函数:
import { StyleSheet, View, Image } from 'react-native'
import React, { useEffect, useState } from 'react'
import { useNavigation } from '@react-navigation/native';
import { getAuth, onAuthStateChanged, signInWithEmailAndPassword } from 'firebase/auth';
import {Title, Button, Headline, Subheading, Text, TextInput} from 'react-native-paper';
export default function LoginComponent() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigation = useNavigation();
const auth = getAuth();
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user) {
navigation.navigate("Category");
}
})
return unsubscribe
}, [])
const handleLogin = () => {
signInWithEmailAndPassword(auth, email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with: ', user);
})
.catch(error => alert(error.message))
}
return (
<View style={styles.container}>
<View>
<Image style={{width: 120, height: 80, resizeMode: 'center'}} source=
{require('./41-410195_blue-cloud-clipart.png')} />
</View>
<View>
<Title style={styles.title}>The Organizer {"\n"}</Title>
</View>
<View>
<Headline>Sign in</Headline>
<Subheading>Hi there! Nice to see you again</Subheading>
</View>
<View>
<Text style={styles.inputText}>E-mail:</Text>
<TextInput style={styles.input} placeholder="Enter your email" value={email}
onChangeText={text => setEmail(text)}/>
<Text style={styles.inputText}>Password:</Text>
<TextInput style={styles.input} secureTextEntry placeholder="Enter your
password"
value={password} onChangeText={text => setPassword(text)}/>
</View>
<View>
<Button style={styles.buttonLogin} mode="contained" uppercase={false}
onPress={handleLogin}>
Login
</Button>
</View>
<View style={styles.buttonSignUpAndPassword}>
<Button style={styles.buttonContainer} uppercase={false} onPress={() =>
{navigation.navigate("SignUp")}}>
Sign up here
</Button>
<View style={styles.space} />
<Button style={styles.buttonContainer} uppercase={false} onPress={() =>
{navigation.navigate("ForgotPassword")}}>
Forgot password?
</Button>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginTop: 50
},
title: {
fontSize: 32,
fontWeight: 'bold',
},
inputText: {
paddingLeft: 14,
paddingTop: 8
},
input: {
padding: 10,
margin: 15,
width: 320,
height: 30,
},
buttonLogin: {
width: 200
},
buttonSignUpAndPassword: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 180
},
buttonContainer: {
flex: 1
},
space: {
width: 50,
height: 20,
},
});
我认为我需要创建三个模拟函数,因为 auth、onAuthStateChanged 和 signInWithEmailAndPassword 在我的快照测试可以 运行 成功之前。
这就是我在 login.test.js 中的做法:
import React from 'react';
import renderer from 'react-test-renderer'
import LoginComponent from '../components/Login/LoginComponent';
jest.mock('firebase/auth', () => {
return {
auth: jest.fn().mockReturnThis(),
signInWithEmailAndPassword: jest.fn(() => mockSignIn),
onAuthStateChanged: jest.fn(() => mockUserState)
}
})
test('renders loginComponent correctly', () => {
const tree = renderer.create(<LoginComponent/>).toJSON();
expect(tree).toMatchSnapshot();
});
这是我收到的错误:
The error
我不知道为什么在快照测试时会出现导航错误。我更担心我对 firebase 函数的模拟没有以正确的方式完成。
问题似乎与 useNavigation
挂钩有关。您可能需要
(1) 为 useNavigation 设置模拟:
const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
const actualNav = jest.requireActual('@react-navigation/native');
return {
...actualNav,
useNavigation: () => ({
navigate: mockedNavigate,
})
};
});
或
(2) 从 @react-navigation/native
导入 NavigationContainer
并在进行测试时用它包裹你的组件,如下所示:
import { NavigationContainer } from '@react-navigation/native';
...
...
test('renders loginComponent correctly', () => {
const tree = renderer.create(
<NavigationContainer>
<LoginComponent/>
</NavigationContainer>
).toJSON();
expect(tree).toMatchSnapshot();
});
注意:为简洁起见,以上只是一些虚拟代码。
其他一些considerations/food供思考:
当您模拟 firebase/auth
时,您可能还必须为 getAuth
设置模拟
signInWithEmailAndPassword
returns 一个承诺,因此您的模拟必须类似于 jest.mockResolvedValue()
而不仅仅是 jest.fn()
,所以希望您的 mockSignIn
价值正在处理
测试愉快!
我在 React Native 项目中工作,我想用 Jest 对我的 LoginComponent 进行快照测试。
LoginComponent.js 在这里看到,我正在使用 firebase 的一些函数:
import { StyleSheet, View, Image } from 'react-native'
import React, { useEffect, useState } from 'react'
import { useNavigation } from '@react-navigation/native';
import { getAuth, onAuthStateChanged, signInWithEmailAndPassword } from 'firebase/auth';
import {Title, Button, Headline, Subheading, Text, TextInput} from 'react-native-paper';
export default function LoginComponent() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigation = useNavigation();
const auth = getAuth();
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user) {
navigation.navigate("Category");
}
})
return unsubscribe
}, [])
const handleLogin = () => {
signInWithEmailAndPassword(auth, email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with: ', user);
})
.catch(error => alert(error.message))
}
return (
<View style={styles.container}>
<View>
<Image style={{width: 120, height: 80, resizeMode: 'center'}} source=
{require('./41-410195_blue-cloud-clipart.png')} />
</View>
<View>
<Title style={styles.title}>The Organizer {"\n"}</Title>
</View>
<View>
<Headline>Sign in</Headline>
<Subheading>Hi there! Nice to see you again</Subheading>
</View>
<View>
<Text style={styles.inputText}>E-mail:</Text>
<TextInput style={styles.input} placeholder="Enter your email" value={email}
onChangeText={text => setEmail(text)}/>
<Text style={styles.inputText}>Password:</Text>
<TextInput style={styles.input} secureTextEntry placeholder="Enter your
password"
value={password} onChangeText={text => setPassword(text)}/>
</View>
<View>
<Button style={styles.buttonLogin} mode="contained" uppercase={false}
onPress={handleLogin}>
Login
</Button>
</View>
<View style={styles.buttonSignUpAndPassword}>
<Button style={styles.buttonContainer} uppercase={false} onPress={() =>
{navigation.navigate("SignUp")}}>
Sign up here
</Button>
<View style={styles.space} />
<Button style={styles.buttonContainer} uppercase={false} onPress={() =>
{navigation.navigate("ForgotPassword")}}>
Forgot password?
</Button>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginTop: 50
},
title: {
fontSize: 32,
fontWeight: 'bold',
},
inputText: {
paddingLeft: 14,
paddingTop: 8
},
input: {
padding: 10,
margin: 15,
width: 320,
height: 30,
},
buttonLogin: {
width: 200
},
buttonSignUpAndPassword: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 180
},
buttonContainer: {
flex: 1
},
space: {
width: 50,
height: 20,
},
});
我认为我需要创建三个模拟函数,因为 auth、onAuthStateChanged 和 signInWithEmailAndPassword 在我的快照测试可以 运行 成功之前。
这就是我在 login.test.js 中的做法:
import React from 'react';
import renderer from 'react-test-renderer'
import LoginComponent from '../components/Login/LoginComponent';
jest.mock('firebase/auth', () => {
return {
auth: jest.fn().mockReturnThis(),
signInWithEmailAndPassword: jest.fn(() => mockSignIn),
onAuthStateChanged: jest.fn(() => mockUserState)
}
})
test('renders loginComponent correctly', () => {
const tree = renderer.create(<LoginComponent/>).toJSON();
expect(tree).toMatchSnapshot();
});
这是我收到的错误: The error
我不知道为什么在快照测试时会出现导航错误。我更担心我对 firebase 函数的模拟没有以正确的方式完成。
问题似乎与 useNavigation
挂钩有关。您可能需要
(1) 为 useNavigation 设置模拟:
const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
const actualNav = jest.requireActual('@react-navigation/native');
return {
...actualNav,
useNavigation: () => ({
navigate: mockedNavigate,
})
};
});
或
(2) 从 @react-navigation/native
导入 NavigationContainer
并在进行测试时用它包裹你的组件,如下所示:
import { NavigationContainer } from '@react-navigation/native';
...
...
test('renders loginComponent correctly', () => {
const tree = renderer.create(
<NavigationContainer>
<LoginComponent/>
</NavigationContainer>
).toJSON();
expect(tree).toMatchSnapshot();
});
注意:为简洁起见,以上只是一些虚拟代码。
其他一些considerations/food供思考:
当您模拟
时,您可能还必须为firebase/auth
getAuth
设置模拟signInWithEmailAndPassword
returns 一个承诺,因此您的模拟必须类似于jest.mockResolvedValue()
而不仅仅是jest.fn()
,所以希望您的mockSignIn
价值正在处理
测试愉快!