英文:
how to test if a function was executed when clicking on the button?
问题
Sure, here's the translated code portion:
我已经实现了下面的组件,其中包含有关产品的信息以及一个按钮,当按下该按钮时,会将用户重定向到详细信息屏幕。
export default function ProductItem(props: ProductItemProps) {
const {navigate} = useNavigation<any>();
const {title, id, rating, category, price, thumbnail} = props;
function navigateToProduct() {
navigate('Product', {id, title});
}
return (
<TouchableOpacity
testID="button-nav"
style={styles.container}
activeOpacity={0.75}
onPress={navigateToProduct}>
<Image source={{uri: thumbnail, width: 100, height: 100}} />
<View style={styles.contentInfo}>
<Text style={styles.title}>{title}</Text>
<Text>{category}</Text>
<StarRating rating={rating} />
<Text style={styles.price}>R${price}</Text>
</View>
</TouchableOpacity>
);
}
Regarding your question about testing if the function is executed, you can use Jest's jest.fn()
to create a mock function and then spy on it using spyOn
. Here's an example of how you can modify your test to check if navigateToProduct
is executed:
import {fireEvent, render, screen} from '@testing-library/react-native';
import ProductItem from '..';
describe('<ProductItem/>', () => {
const product = {
title: 'title-test',
id: 1,
rating: 4.5,
category: 'category-test',
price: 499,
thumbnail: 'thumbnail-test',
description: 'description-test',
stock: 1,
brand: 'brand-test',
images: ['image1-test', 'image2-test'],
};
it('Should render correctly product item component', () => {
render(<ProductItem {...product} />);
const title = screen.getByText(product.title);
expect(title).toBeTruthy();
});
it('Should navigate to product screen when button pressed', async () => {
// Create a mock function
const navigateMock = jest.fn();
// Mock the useNavigation hook to return the mock function
jest.mock('@react-navigation/native', () => ({
...jest.requireActual('@react-navigation/native'),
useNavigation: () => ({
navigate: navigateMock,
}),
}));
render(<ProductItem {...product} />);
const toPress = screen.getByTestId('button-nav');
fireEvent.press(toPress);
// Check if the navigate function was called with the expected arguments
expect(navigateMock).toHaveBeenCalledWith('Product', { id: product.id, title: product.title });
});
});
This code creates a mock function for the navigate
function and ensures that it's called with the expected arguments when the button is pressed in your component.
英文:
I have implemented the component below, which is a card containing information about a product and a button that, when pressed, redirects the user to the details screen.
export default function ProductItem(props: ProductItemProps) {
const {navigate} = useNavigation<any>();
const {title, id, rating, category, price, thumbnail} = props;
function navigateToProduct() {
navigate('Product', {id, title});
}
return (
<TouchableOpacity
testID="button-nav"
style={styles.container}
activeOpacity={0.75}
onPress={navigateToProduct}>
<Image source={{uri: thumbnail, width: 100, height: 100}} />
<View style={styles.contentInfo}>
<Text style={styles.title}>{title}</Text>
<Text>{category}</Text>
<StarRating rating={rating} />
<Text style={styles.price}>R${price}</Text>
</View>
</TouchableOpacity>
);
}
So far, I've already implemented the test to check the component's rendering, but I need to test if when the button is pressed, the "navigateToProduct" function will be executed.
import {fireEvent, render, screen} from '@testing-library/react-native';
import ProductItem from '..';
describe('<ProductItem/>', () => {
const product = {
title: 'title-test',
id: 1,
rating: 4.5,
category: 'category-test',
price: 499,
thumbnail: 'thumbnail-test',
description: 'description-test',
stock: 1,
brand: 'brand-test',
images: ['image1-test', 'image2-test'],
};
it('Should render correctly product item component', () => {
render(<ProductItem {...product} />);
const title = screen.getByText(product.title);
expect(title).toBeTruthy();
});
it('Should navigate to product screen when button pressed', async () => {
render(<ProductItem {...product} />);
const toPress = screen.getByTestId('button-nav');
fireEvent.press(toPress);
});
});
The whole mock of react navigation "useNavigation" already works. And until then, the tests are all passing. My question is just how can I test if the function is executed. I've tried using spyOn, but I don't know exactly how I can mock this function within my tests. Can anyone give me any suggestions?
答案1
得分: 0
你可以使用jest.fn()
创建一个模拟函数,并在触发按键事件后使用expect(mockFn).toBeCalled()
来测试该函数是否已被调用。以下是来自React Native Testing Library文档的示例(根据您的用例,可以交换toBeCalledWith
和toBeCalled
):
test('form submits two answers', () => {
const allQuestions = ['q1', 'q2'];
const mockFn = jest.fn();
render(<QuestionsBoard questions={allQuestions} onSubmit={mockFn} />);
const answerInputs = screen.getAllByLabelText('answer input');
fireEvent.changeText(answerInputs[0], 'a1');
fireEvent.changeText(answerInputs[1], 'a2');
fireEvent.press(screen.getByText('Submit'));
expect(mockFn).toBeCalledWith({
1: { q: 'q1', a: 'a1' },
2: { q: 'q2', a: 'a2' },
});
});
请注意,上述代码是用于测试React Native组件的示例。
英文:
You can create a mock function with jest.fn()
and use expect(mockFn).toBeCalled()
after firing the key press even to test if the function has been called. Here is an example from the React Native Testing Library docs (swap toBeCalledWith
and toBeCalled
for your use case):
test('form submits two answers', () => {
const allQuestions = ['q1', 'q2'];
const mockFn = jest.fn();
render(<QuestionsBoard questions={allQuestions} onSubmit={mockFn} />);
const answerInputs = screen.getAllByLabelText('answer input');
fireEvent.changeText(answerInputs[0], 'a1');
fireEvent.changeText(answerInputs[1], 'a2');
fireEvent.press(screen.getByText('Submit'));
expect(mockFn).toBeCalledWith({
1: { q: 'q1', a: 'a1' },
2: { q: 'q2', a: 'a2' },
});
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论