状态未设置开玩笑模拟

时间:2020-08-03 21:18:49

标签: reactjs testing jestjs

组件代码:

constructor(props) {
        super(props);

        this.handleAuthentication = this.handleAuthentication.bind(this);

        this.state = {
            validAuthCode: true,
        }
    }

    async handleAuthentication(e) {
        e.preventDefault();
    
        try {
            let validAuthCode = await createPermanentAuth(this.state.authCode);
            if (validAuthCode) {
                this.props.history.push("/");
            }
            this.setState({ validAuthCode: false });
        } catch(e) {
            // error handling
        }
    }

    render() {
        return (
            <form onSubmit={this.handleAuthentication.bind(this)} data-testid="create-permanent-auth">
                <label htmlFor="code">Auth code:</label>
                <input id="code"
                    name="code" 
                    placeholder="12345" 
                    className={this.state.validAuthCode ? 'valid-data' : 'invalid-data'}
                    onChange={this.handleAuthCodeChange.bind(this)} />
                <input type="submit" value="Submit" />
            </form>
        );
    }

测试:

jest.mock('../yasClient');
.
. 
import { createPermanentAuth } from '../yasClient';

beforeEach(() => {
    token = screen.getByLabelText('Auth code:');
    
    expect(screen.queryByTestId('bad-code-message').classList.contains('hidden')).toBe(true);
});


it("shows authcode outlined in red and error message displayed, when bad token entered.", () => {
    createPermanentAuth.mockReturnValueOnce(false);

    fireEvent.change(token, {  target: { value: '1' } });
    fireEvent.submit(screen.getByTestId('create-permanent-auth'));

    expect(createPermanentAuth).toHaveBeenCalledTimes(1);
    expect(token.classList.contains('invalid-data')).toBe(true);
    expect(screen.getByTestId('bad-code-message').classList.contains('visible')).toBe(true);
});

无论出于何种原因,看起来validAuthCode都不会设置为false。

token.classList.contains('valid-data')返回true,我希望token.classList.contains('invalid-data')返回true。

我想知道我是否想念一些东西。我猜测问题可能与异步性和/或setState的调用方式有关。

2 个答案:

答案 0 :(得分:0)

您需要在发生这种火灾事件时将更新状态包装起来:

await act(async()=>{
     await fireEvent.change(token, {  target: { value: '1' } });
     fireEvent.submit(screen.getByTestId('create-permanent-auth'));
 })
await act(async ()=>Promise.reslove())

这确保您正在测试真实行为。 注意:此处我为令牌组件上的await添加了fireEvent,因为我不希望按钮在令牌事件更新状态之前触发submit event

答案 1 :(得分:0)

最终花钱在codementor上以得到这个答案。

测试用例

c(Q01, Q02)

beforeEach

it("navigates to '/', when a good token is entered.", async() => {
    createPermanentAuthSpy.mockImplementationOnce(() => Promise.resolve(true));
    await act(async() => {
        await fireEvent.change(token, {  target: { value: '1' } });
        fireEvent.submit(screen.getByTestId('create-permanent-auth'));
    });

    expect(createPermanentAuthSpy).toHaveBeenCalledTimes(1);
    expect(token.classList.contains('valid-data')).toBe(true);
    expect(screen.queryByTestId('bad-code-message').classList.contains('hidden')).toBe(true);
});

我不确定我所拥有的模拟技术与它之间有什么区别-但这可以工作。