【问题标题】:I want to spyOn method, return value, and continue running through the script我要 spyOn 方法,返回值,然后继续运行脚本
【发布时间】:2020-09-04 08:01:00
【问题描述】:

我正在监视一个方法,在这种情况下:axios.post。我想解决它并继续运行脚本,因为在then 块中,它必须运行另一个方法。我目前解决它的方法是使用jest.spyOn(axios, 'post').mockImplementation(() => Promise.resolve( ));。正如它所说,这是一个模拟实现,并将完全放弃实际代码。我想要的是一种解决此调用的方法(通过returnValue 或其他方式)并继续执行实际代码。我记得Jasmin 有类似的效果。

编辑: 我似乎 axios promise.resolve 实际上正在推进它。问题更多在于我试图模拟 helpers.showResponseMessage 并且 Jest 一直坚持不调用它(即使模拟中的 console.log 被调用)。有什么想法吗?

联系方式(我正在尝试正确解决 Axios 呼叫)

const recommendationHandler = (event) => {
        event.preventDefault();
        axios.post('/contact.json', extractData(config.addMessage))
            .then(() => {
                showResponseMessage(`Din besked er sendt.`, initialState, false, setConfig, 5000);
            })
            .catch(() => {
                showResponseMessage(`Der opstod en fejl ved sendning. Prøv igen senere.`, {}, true, setConfig, 10000);
            });
    }

测试文件

import React from 'react';
import { configure, shallow, mount, render } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import axios from '../../axios-instances/axios-firebase'
import * as helpers from '../../utility/Helpers/Helpers'
import Contact from './Contact';

configure({ adapter: new Adapter() });

describe('<Contact />', () => {
    it.only('should POST data to server if necessary payload is included', async () => {
        jest.spyOn(axios, 'post').mockImplementation(() => Promise.resolve( ));
        const wrapper = mount(<Contact />);
        jest.spyOn(helpers, 'showResponseMessage').mockImplementationOnce(_ => console.log('test'));

        wrapper.find('form').simulate('submit', {
            preventDefault: () => { }
        });

        expect(axios.post).toHaveBeenCalledTimes(1);
        expect(helpers.showResponseMessage).toHaveBeenCalled();
        expect(wrapper.find('#responseMessage')).toHaveLength(1);

    });
});

【问题讨论】:

    标签: reactjs jestjs axios


    【解决方案1】:

    一如既往地提供 Stackoverflow。

    显然您需要输入await Promise.resolve() 以将其拆分为微任务。我不太确定它是如何工作的,如果有人能解释一下,那就太好了。

    Stackoverflow 回答:How to test async function with spyOn?

    describe('<Contact />', () => {
        it.only('should POST data to server if necessary payload is included', async () => {
            jest.spyOn(axios, 'post').mockImplementation(() => Promise.resolve( ));
            const wrapper = mount(<Contact />);
            jest.spyOn(helpers, 'showResponseMessage').mockImplementationOnce(_ => console.log('test'));
    
            wrapper.find('form').simulate('submit', {
                preventDefault: () => { }
            });
    
            expect(axios.post).toHaveBeenCalledTimes(1);
            await Promise.resolve(); <-- THIS IS APPARENTLY A MICROTASK
            expect(helpers.showResponseMessage).toHaveBeenCalled();
            expect(wrapper.find('#responseMessage')).toHaveLength(1);
    
        });
    });
    

    【讨论】:

    • 之所以有效,是因为 showResponseMessage 是异步调用的,延迟了一个承诺长度,并且您至少需要在测试中进行相同的延迟才能与它相提并论。 await Promise.resolve() 是多余的,因为await 对任何值都执行Promise.resolve,可能是await null。更精确的方法是等待您正在等待的特定承诺,这是请求返回的虚拟承诺,即await axios.post.mock.results[0].value。如果 RecommendationHandler 中有更多嵌套的 Promise,这可能不起作用。
    • 感谢 Estus 的解释,这很有意义。我会尝试你的虚拟承诺,但为什么它更精确?我似乎没有将那个 results[0].value 用于任何事情。纯粹是为了语义和解释我在等待什么?
    • 没错。如果 axios.post 没有被模拟而是被监视,或者被模拟为不能立即解决(网络请求应该在测试中被模拟,但这也适用于其他异步 API),那将会有所不同。
    猜你喜欢
    • 1970-01-01
    • 2011-09-07
    • 2021-08-02
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多