模拟在另一个函数中使用的函数

3

我正在编写针对React Redux中异步操作的测试,为了解决问题,我在这里简化了代码。以下是我的action函数:

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?
2个回答

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。

在场景中,如果您想要存根(mock)或模拟(private imports),而这些东西并没有用在像axios请求这样的地方,那么您可以使用rewire或者babel-plugin-rewire,如果您正在使用import等es6语法。

如果您完全不知道路径,您可以像这样做:onGet('/'),所有的内容都在README.md中。在测试结束后,我想有一种方法可以重置它,以便不会影响使用axios的所有测试。

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

非常感谢您的回答,我会开始研究并告诉您结果。只是一个问题:我有一个函数getLoginStatusUrl用于获取URL,我们根本不知道路径,但在这里的模拟函数中,我们有onGet('/loginStatus'),它定义了路径'/loginStatus',它如何解决这个问题? - Hamed Minaee
非常感谢,我正在处理中,结果出来后会通知您。 - Hamed Minaee
当我查看此项目的自述文件时:如果您完全不知道路径,可以像 onGet('/') 这样做。但是我找不到任何东西。我错过了什么吗? - Hamed Minaee
@HamedMinaee 或者指定没有路径,例如 onGet()。这在自述文件中有说明。 - Martin Dawson

2

使用sinon试试这个。

import {getLoginStatusUrl} from './some/path.js'

let stub = sinon.stub(),
opts = { call: getLoginStatusUrl() };

stub.withExactArgs().returns("somePredefinedReturnValue")

谢谢,如果 getLoginStatusUrl 是一个私有函数,这个代码还能正常工作吗? - Hamed Minaee
为了编写代码的最佳实践,导出函数是否因测试目的而是一个好主意? - Hamed Minaee
通常我们不会仅为了测试而更改代码。你是在操作中调用本地函数吗?如果是这样,你可以将其导出为ES模块,并在测试文件中导入它。只需在函数定义的开头添加“export”即可。顺便说一下,如果该函数是本地的,则无法进行单元测试。 - Ravindra Ranwala
@RavindraRanwala 如果你要这样做,不要导出它,而是使用我在答案中提供的rewire。 - Martin Dawson
最好的选择是将其作为属性传递给组件。然后在您的测试中,您也可以像这样传递属性。 `_props = { prop1: 'value1', getLoginStatusUrl : (_spies.getLoginStatusUrl = sinon.spy()),} _wrapper = shallow()` - Ravindra Ranwala
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接