如何在我的 class 组件中测试方法?
How do I test method inside my class component?
我有这个方法:
fizzBuzz = () => {
let tokens = [];
for (let i=1; i <= this.state.upperLimit; i++) {
if (i % 15 === 0) {
tokens.push("fizzbuzz");
} else if (i % 3 === 0) {
tokens.push("fizz");
} else if (i % 5 === 0) {
tokens.push("buzz");
} else {
tokens.push(i) ;
}
}
this.setState({message: tokens.join(" ")});
}
这只是 FizzBuzz 计算,让用户在输入字段中输入 fizzbuzz 实施的上限并提交。然后上面的方法进行一些计算并在屏幕上显示消息。
渲染内部的片段-return:
<input value={this.upperLimit} type="number" min="1" placeholder="Enter Integer"/>
<button type="button" onClick={this.fizzBuzz}>Submit</button>
<label>{this.state.message}</label>
我正在使用 Jest 和 React-Testing-Library,但我不确定如何测试此功能。我是否需要重新安排我的 class 组件内部的完成方式以使其可访问以供测试?
RTL suggests to test like a real user would,所以你应该根据显示的组件编写测试:
- 更改输入值
- 点击按钮
- 测试标签中是否存在请求的消息
- 使用不同的输入编写其他类似测试以涵盖所有情况。
所以好消息是您不需要对您的组件进行任何更改,您的单元测试应该与内部实现分离。 The implementation may change, without having to rewrite all your tests.
有关此主题的详细说明,请参阅 this issue。
你的测试可能是这样的:
describe('fizzbuzz', () => {
let rtl: RenderResult;
beforeEach(() => {
rtl = render(<Fizzbuzz />);
});
test('prints correct tokens for 16', () => {
// I assume that the input has a label which is "label for input"
// I order to test like a real user you should grab DOM elements with visual properties/texts
// and avoid things like CSS selectors. data-testid attribute should be the last option to use
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '16' } });
// ...but you can still use querySelector/querySelectorAll
fireEvent.click(rtl.container.querySelector('button'));
// check that what should be returned by the function is present in the document
expect(rtl.getByText('0 1 2 fizz 4 buzz fizz 7 8 fizz 10 11 fizz 13 14 fizzbuzz 16')).toBeTruthy();
});
test('prints correct tokens for various other cases', () => {
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '4' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.getByText('0 1 2 fizz 4')).toBeTruthy();
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '7' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.getByText('0 1 2 fizz 4 buzz fizz 7')).toBeTruthy();
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '0' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.getByText('0')).toBeTruthy();
});
test('behaves correctly with negative input', () => {
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '-7' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.container.querySelector('label').textContent).toEqual('');
});
// add more if you feel that some cases are not covered
// BTW the above tests should give you a 100% test coverage
// This should not be a goal (you can get 100% test coverage passing for wrong code),
// but it is still a good indicator.
// https://jestjs.io/docs/en/cli.html#--coverageboolean
});
我有这个方法:
fizzBuzz = () => {
let tokens = [];
for (let i=1; i <= this.state.upperLimit; i++) {
if (i % 15 === 0) {
tokens.push("fizzbuzz");
} else if (i % 3 === 0) {
tokens.push("fizz");
} else if (i % 5 === 0) {
tokens.push("buzz");
} else {
tokens.push(i) ;
}
}
this.setState({message: tokens.join(" ")});
}
这只是 FizzBuzz 计算,让用户在输入字段中输入 fizzbuzz 实施的上限并提交。然后上面的方法进行一些计算并在屏幕上显示消息。
渲染内部的片段-return:
<input value={this.upperLimit} type="number" min="1" placeholder="Enter Integer"/>
<button type="button" onClick={this.fizzBuzz}>Submit</button>
<label>{this.state.message}</label>
我正在使用 Jest 和 React-Testing-Library,但我不确定如何测试此功能。我是否需要重新安排我的 class 组件内部的完成方式以使其可访问以供测试?
RTL suggests to test like a real user would,所以你应该根据显示的组件编写测试:
- 更改输入值
- 点击按钮
- 测试标签中是否存在请求的消息
- 使用不同的输入编写其他类似测试以涵盖所有情况。
所以好消息是您不需要对您的组件进行任何更改,您的单元测试应该与内部实现分离。 The implementation may change, without having to rewrite all your tests.
有关此主题的详细说明,请参阅 this issue。
你的测试可能是这样的:
describe('fizzbuzz', () => {
let rtl: RenderResult;
beforeEach(() => {
rtl = render(<Fizzbuzz />);
});
test('prints correct tokens for 16', () => {
// I assume that the input has a label which is "label for input"
// I order to test like a real user you should grab DOM elements with visual properties/texts
// and avoid things like CSS selectors. data-testid attribute should be the last option to use
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '16' } });
// ...but you can still use querySelector/querySelectorAll
fireEvent.click(rtl.container.querySelector('button'));
// check that what should be returned by the function is present in the document
expect(rtl.getByText('0 1 2 fizz 4 buzz fizz 7 8 fizz 10 11 fizz 13 14 fizzbuzz 16')).toBeTruthy();
});
test('prints correct tokens for various other cases', () => {
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '4' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.getByText('0 1 2 fizz 4')).toBeTruthy();
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '7' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.getByText('0 1 2 fizz 4 buzz fizz 7')).toBeTruthy();
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '0' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.getByText('0')).toBeTruthy();
});
test('behaves correctly with negative input', () => {
fireEvent.change(rtl.getByLabelText('label for input'), { target: { value: '-7' } });
fireEvent.click(rtl.container.querySelector('button'));
expect(rtl.container.querySelector('label').textContent).toEqual('');
});
// add more if you feel that some cases are not covered
// BTW the above tests should give you a 100% test coverage
// This should not be a goal (you can get 100% test coverage passing for wrong code),
// but it is still a good indicator.
// https://jestjs.io/docs/en/cli.html#--coverageboolean
});