【问题标题】:How do I make Nock and Mocha play well together?如何让 Nock 和 Mocha 配合得很好?
【发布时间】:2017-05-27 22:13:45
【问题描述】:

我正在尝试使用 nock 来拦截/模拟我的应用程序中的一些 HTTP 流量以进行测试。我们的应用程序向我们的另一个站点进行身份验证,我需要 nock 来模拟 HTTP 200(带有 JSON 数据)和 HTTP 401(没有数据)来测试用户登录或未登录时的行为(分别) .

我有两个测试在单独运行时都可以正常工作,但是如果我运行整个测试套件,其中一个总是失败。我意识到 nock 是共享状态,因为它修改了 node.js 本身处理网络流量的方式,我认为这是竞争条件的原因,但我不能是唯一一个曾经为同一个请求使用两个不同的 nock 拦截器的人两个不同的测试,所以我知道我错过了一些东西。

谁能帮我弄清楚为什么这些测试会互相影响?

我的问题与How to retest same URL using Mocha and Nock? 有关,但我做了那里建议的事情,但它们没有帮助。

我的测试文件(同样,如果单独调用它们都可以正常工作,但在作为同一测试通过的一部分运行时会失败)如下所示:

import { expect } from 'chai';
import nock from 'nock';

import * as actionTypes from '../../src/constants/action-types';
import * as panoptes from '../../src/services/panoptes';

import { user } from '../modules/users/test-data';

const stagingHost = 'https://my-staging-server.org';

describe('Panoptes', () => {
  afterEach(function (done) {
    nock.cleanAll();
    nock.disableNetConnect();
    done();
  });

  beforeEach(function (done) {
    nock.cleanAll();
    nock.disableNetConnect();
    done();
  });

  describe('with a valid user', function (done) {
    let lastAction = null;

    const scope = nock(stagingHost)
      .get(/^\/oauth\/authorize/)
      .reply(302, '', {
        'location': 'https://localhost:3000',
        'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
        'X-Frame-Options': 'SAMEORIGIN',
        'X-XSS-Protection': '1; mode=block',
      });

    scope
      .get(/^\/api\/me/)
      .reply(200, {
        users: [user],
      });

    panoptes.checkLoginUser((action) => { lastAction = action; }).then(() => {
      nock.removeInterceptor(scope);
      done();
    });

    it('should know when somebody is logged in', function () {
      expect(lastAction).to.not.be.null;
      expect(lastAction.type).to.equal(actionTypes.SET_LOGIN_USER);
      expect(lastAction.user).to.not.be.null;
      expect(lastAction.user.id).to.equal(user.id);
      expect(lastAction.user.login).to.equal(user.login);
    });
  });
});

import { expect } from 'chai';
import nock from 'nock';

import * as actionTypes from '../../src/constants/action-types';
import * as panoptes from '../../src/services/panoptes';

const stagingHost = 'https://my-staging-server.org';

describe('Panoptes', () => {
  afterEach(function (done) {
    nock.cleanAll();
    nock.disableNetConnect();
    done();
  });

  beforeEach(function (done) {
    nock.cleanAll();
    nock.disableNetConnect();
    done();
  });

  describe('with no user', function (done) {
    let lastAction = null;

    const scope = nock(stagingHost)
      .get(/^\/oauth\/authorize/)
      .reply(302, '', {
        'Cache-Control': 'no-cache',
        'location': 'https://my-staging-server.org/users/sign_in',
        'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
        'X-Frame-Options': 'SAMEORIGIN',
        'X-XSS-Protection': '1; mode=block',
      });

    scope
      .get(/^\/api\/me/)
      .reply(401);

    panoptes.checkLoginUser((action) => { lastAction = action; }).then(() => {
      nock.removeInterceptor(scope);
      done();
    });

    it('should know that nobody is logged in', function () {
      expect(lastAction).to.not.be.null;
      expect(lastAction.type).to.equal(actionTypes.SET_LOGIN_USER);
      expect(lastAction.user).to.be.null;
    });
  });
});

【问题讨论】:

  • 同时运行这两个测试时看到什么错误?
  • 我没有收到错误,实际上,只是第二次测试在应该通过时失败了。似乎第二个测试受到第一个测试的模拟的影响。

标签: node.js testing asynchronous mocha.js nock


【解决方案1】:

我认为问题不在于 nock,而在于你的 mocha 钩子的执行顺序:

举个例子:

describe('Panoptes', () => {

  afterEach(function () {
    console.log('ORDER: after each');
  });

  beforeEach(function () {
    console.log('ORDER: before each');
  });

  describe('with a valid user', function () {

    console.log('ORDER: with a valid user');

    it('should know when somebody is logged in', function () {
      console.log('ORDER: should know when somebody is logged in');
    });

  });

  describe('with no user', function () {

    console.log('ORDER: with no user');

    it('should know that nobody is logged in', function () {
      console.log('ORDER: should know that nobody is logged in');
    });

  });

});

当我们运行它时,我们得到以下输出顺序:

ORDER: with a valid user
ORDER: with no user
ORDER: before each
ORDER: should know when somebody is logged in
ORDER: after each
ORDER: before each
ORDER: should know that nobody is logged in
ORDER: after each

afterEach/beforeEach 在每个 it 之前和之后运行,但是 describe 主体在调用这些钩子之前被评估。您应该将每个 nocks 包裹在 before 中。 (另外describe 不使用done 参数)

这样的事情应该可以工作:

describe('with no user', function () {

  before(function() {
    const scope = nock(stagingHost)
      .get(/^\/oauth\/authorize/)
      .reply(302, '', {
        'Cache-Control': 'no-cache',
        'location': 'https://my-staging-server.org/users/sign_in',
        'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
        'X-Frame-Options': 'SAMEORIGIN',
        'X-XSS-Protection': '1; mode=block',
      });

    scope
      .get(/^\/api\/me/)
      .reply(401);
  });


  it('should know that nobody is logged in', function (done) {
    panoptes.checkLoginUser((action) => {
      expect(action).to.not.be.null;
      expect(action.type).to.equal(actionTypes.SET_LOGIN_USER);
      expect(action.user).to.be.null;
      done();
    });
  });

});

【讨论】:

  • 非常感谢您的建议!一旦我看到这是否解决了问题,我会尝试并发表评论。
  • 这正是我所需要的。不幸的是,我的测试仍然失败,但现在问题出在我们的代码中,并且因为我之前测试错了,所以我没有看到它!
【解决方案2】:

我使用了 sanketh-katta 的答案,我将其归功于解决方案,但稍微修改了 it 块,因此我将我的代码包括在内以确保完整性:

it('should know when somebody is logged in', function(done) {
  panoptes.checkLoginUser((action) => {
    try {
      expect(action).to.not.be.null;
      expect(action.type).to.equal(actionTypes.SET_LOGIN_USER);
      expect(action.user).to.not.be.null;
      expect(action.user.id).to.equal(user.id);
      expect(action.user.login).to.equal(user.login);
      done();
    } catch (ex) {
      done(ex);
    }
  });
});

以前,当其中一个测试失败时,done() 调用将永远无法到达,因此我会收到测试已超时而不是特定失败的消息。

【讨论】:

猜你喜欢
  • 2014-04-07
  • 2019-05-18
  • 1970-01-01
  • 2011-10-24
  • 2016-08-18
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
相关资源
最近更新 更多