【问题标题】:mock a function which is used in another function模拟在另一个函数中使用的函数
【发布时间】:2018-01-21 15:09:41
【问题描述】:

我正在为我在 react redux 中的异步操作编写测试,为了解决我在此处简化代码的问题。这是我的动作函数:

export function updateUserAuthenticationStatus(){
return function(dispatch){
   return axios.get(getLoginStatusUrl())
        .then(response => {
               const middlewares = [thunk];
               const mockStore = configureMockStore(middlewares);
               const store = mockStore();
    return store.dispatch(updateUserAuthenticationStatus()).then(()=>{
       //expect(store.getActions()[0]).to.eql(expectedActions);
    });
            });
        }).catch(function(response){
    });
  }
}

所以问题在于函数 getLoginStatusUrl() 会在 cookie 中进行几次检查并根据某些条件返回适当的 url。所以我想要模拟这个函数以返回例如 test.com 然后我可以按如下方式测试我的操作:

it("", () => {
        **here I want to mock getLoginStatusUrl() to return test.com**
    nock("test.com")
        .get("/")
        .reply(200,"test detail");

})

在这种情况下如何模拟 getLoginStatusUrl() 以返回 test.com?

【问题讨论】:

    标签: reactjs redux react-redux jestjs reactjs-testutils


    【解决方案1】:

    用 sinon 试试这个。

    import {getLoginStatusUrl} from './some/path.js'
    
    let stub = sinon.stub(),
    opts = { call: getLoginStatusUrl() };
    
    stub.withExactArgs().returns("somePredefinedReturnValue")
    

    【讨论】:

    • 谢谢,如果 getLoginStatusUrl 是私有函数,这行得通吗?
    • 将函数导出为像export function getLoginStatusUrl() {...}这样的ES模块,然后在这里导入。我假设你在你的行动中做同样的事情。
    • 是的,但是为了编写代码的最佳实践,由于测试目的而导出函数是个好主意吗?
    • 通常我们不会为了测试而改变代码。您是否在操作中调用本地函数?如果是这样,您可以将其导出为 ES 模块并将其导入您的测试文件。只需在函数定义的开头添加export。顺便说一句,如果函数是本地的,那么你甚至不能对其进行单元测试。
    【解决方案2】:

    您不需要专门返回 test.com。使用诸如axios-mock-adapter 之类的库。我没有亲自使用它,但我使用 fetch-mock 来模拟 fetch api 请求,因此这个概念应该完全相同。

    假设getLoginStatusUrl() 返回/loginStatus,(因为您还没有显示它返回的内容)。

    例子:

    var axios = require('axios');
    var MockAdapter = require('axios-mock-adapter');
    
    // This sets the mock adapter on the default instance
    var mock = new MockAdapter(axios);
    
    // Mock any GET request to /users
    // arguments for reply are (status, data, headers)
    mock.onGet('/loginStatus').reply(200, {
      loginSuccess: true
    });
    
    axios.get('/loginStatus')
      .then(function(response) {
        console.log(response.data);
      });
    

    示例代码未经测试,但希望您能理解。只需阅读库 README.md。

    在您想要存根/模拟在这样的 axios 请求中未使用的私有导入的场景中,如果您使用诸如导入之类的 es6 语法,则可以使用 rewirebabel-plugin-rewire

    @HamedMinaee 如果你根本不知道路径,你可以做一些类似onGet('/') 的事情,它都在 README.md 中。在测试之后,我想他们是一种重置它的方法,这样并不是所有使用 axios 的测试都会受到它的影响。

    afterEach(() => {
        // reset the axios mock here so that '/' doesn't affect all requests or something.
    });
    

    【讨论】:

    • 非常感谢您的回答,我将开始调查并让您知道结果。只是一个问题:我有一个函数 getLoginStatusUrl 用于获取 url,我们根本不知道路径,但在模拟函数中,我们有 onGet('/loginStatus') 我们定义了路径 '/loginStatus' 它是如何解决的这个问题?
    • 非常感谢我正在努力,让您知道结果
    • 当我检查自述文件时:如果你根本不知道路径,你可以做类似 onGet('/') 我找不到任何东西。我错过了什么吗?
    • @HamedMinaee 或者不指定路径,例如onGet()。这是自述文件中的内容
    猜你喜欢
    • 2021-04-19
    • 1970-01-01
    • 2019-04-19
    • 2018-08-13
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    相关资源
    最近更新 更多