Nock 在 Redux 测试中没有拦截 API 调用

Posted

技术标签:

【中文标题】Nock 在 Redux 测试中没有拦截 API 调用【英文标题】:Nock is not intercepting API call in Redux test 【发布时间】:2016-07-14 10:12:32 【问题描述】:

我正在尝试在 redux 应用程序中测试 api 调用。代码几乎遵循 redux 文档的 Async Action Creators 部分中概述的模式:

http://redux.js.org/docs/recipes/WritingTests.html

它的要点是你使用 redux-mock-store 来记录和断言任何被触发的动作。

这是整个测试,使用 nock 模拟 api 调用:

import React from 'React'
import ReactDOM from 'react-dom'
import expect from 'expect';
import expectJSX from 'expect-jsx';
import TestUtils from 'react-addons-test-utils'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import nock from 'nock'
expect.extend(expectJSX);

import * as types from '../../constants/Actions'

describe('Async Search Actions', () => 
    const thunkMiddleware = [ thunk ];
     /* use redux-mock-store here */
    const mockStore = configureMockStore(thunkMiddleware);


    describe('The fetchArtistData action creator should', () => 

            afterEach(() => 
                nock.cleanAll()
            )

        it('Should fire off a ARTIST action when fetch is done', (done) => 
            nock('http://ws.audioscrobbler.com')
                .get('/2.0/')
                .query(method: 'artist.search', artist: 'ho', api_key: 'abc123', format: 'json', limit: 5)
                .reply(200, 
                      
                        fake: true
                      
                   )



            const expectedActions = [
                 type: types.ARTIST, artists: 
                        fake: true
                     
                
            ];

            let store = mockStore([], expectedActions, done);
            store.dispatch(fetchArtist('ho'))

        );

    );

);

但似乎在运行测试时调用了真正的 lastFm api...从 lastFm 返回真实数据而不是假的 nock 响应。

这是动作创建者本身:

export function fetchArtist(search) 
    return dispatch => 
        return fetch(`http://ws.audioscrobbler.com/2.0/?method=artist.search&artist=$search&api_key=abc123&format=json&limit=5`)
            .then(handleErrors)
            .then(response => response.json())
            .then(json =>  dispatch(ArtistData(searchTerm, json)) )
            .catch(handleServerErrors)
    

断言失败,因为实时 lastFM 响应与我根据 expectedActions 对象所期望的响应不同..

我尝试将 nock 分配给一个变量并将其注销。日志显示如下:

Nock 似乎正在将端口 80 添加到 url,不确定这是否导致实际 API 未被模拟:

    keyedInterceptors: ObjectGET http://ws.audioscrobbler.com:80/2.0/?
method=artist.search&artist=john&api_key=abc123&format=json&limit=5

有什么想法吗?

【问题讨论】:

你是在节点还是浏览器中运行这个?我不相信 nock 在浏览器中有效,只有节点 啊好吧,那就是问题所在,我正在 PhantomJs 上运行测试 看起来 nock 不喜欢浏览器获取 github.com/node-nock/nock/issues/409。暂时按照建议尝试切换到 fetch-mock 你找到答案了吗?我到处找了,都想不通 您找到解决方案了吗?我的诺克也不是在嘲笑。 【参考方案1】:

在 nock 之后添加 .log(console.log) ,这样您将获得准确的预期和当前 url。 示例:

     nock("http://localhost")
.log(console.log)
.persist()
.get("/api/config")
.reply(200,  data: 1234 )

【讨论】:

【参考方案2】:

要使用 nock,您必须在 node 中运行测试(使用 Jest 或 mocha),nock 会覆盖 node http 行为,因此它仅适用于 node 而不能在浏览器中(如 PhantomJS)。

例如,您指出的链接是使用 Jest 并且第一行是关于节点环境的明确说明。因此,诺克将作为一种魅力。 http://redux.js.org/docs/recipes/WritingTests.html

设置

我们推荐 Jest 作为测试引擎。请注意,它运行 在 Node 环境中,因此您将无法访问 DOM。

我认为你可以:

在节点环境中运行测试 或使用不同的库模拟fetch-mock

【讨论】:

【参考方案3】:

您只需将基本 URL 传递给主 nock 函数,并将 URL 路径部分分离到 .get() 方法中。

nock('http://ws.audioscrobbler.com')
  .get('/2.0/')
  .query(
    method: 'artist.search',
    artist: 'bob',
    api_key: 'somekey123',
    format: 'json',
    limit: '5'
  )
  .reply(200, fake: true)

我能够用上面的代码得到一个虚假的响应。

【讨论】:

我应该提到我已经尝试过这个 - 我仍然使用这个配置从最后一个 fm 获取真实数据 好吧,你需要发布一个MCVE,因为这里还有其他断开连接的东西,但很难猜出那可能是什么。 好的,添加了更多细节 看起来 url 路径不匹配 /202/ vs /2.0/ 不幸的是,这是一个错字

以上是关于Nock 在 Redux 测试中没有拦截 API 调用的主要内容,如果未能解决你的问题,请参考以下文章

错误:在带有 nock 和 mock-store 的 Redux 应用程序的异步操作测试中,操作可能未定义

Redux 使用 jest、nock、axios 和 jsdom 测试 multipart/form-data

Nock 不能与 axios 一起使用获取操作异步测试

使用 Detox 和 Nock 模拟 API 调用

React API 测试与 Nock 失败并出现“错误:Nock:请求不匹配”

使用 nock 和 mocha 测试身份验证时卡住