3

テスト目的で、アプリケーションで一部の HTTP トラフィックをインターセプト/モックするために nock を使用しようとしています。私たちのアプリは私たちのサイトの別の 1 つに対して認証されます。ユーザーがそこにログインしている場合とログインしていない場合の動作をテストするには、nock で HTTP 200 (JSON データあり) と HTTP 401 (データなし) を模倣する必要があります (それぞれ)。 .

単独で実行すると両方とも正しく動作する 2 つのテストがありますが、テスト スイート全体を実行すると、そのうちの 1 つが常に失敗します。node.js 自体がネットワーク トラフィックを処理する方法を変更するため、nock は共有状態であることがわかります。これが競合状態の原因であると思いますが、同じリクエストに対して 2 つの異なる nock インターセプターを使用したことがある人は私だけではありません。 2つの異なるテストなので、何かが欠けていることがわかります。

これらのテストが互いに踏み合っている理由を理解するのを手伝ってくれる人はいますか?

私の質問は、Mocha と Nock を使用して同じ URL を再テストする方法に関連していますか? しかし、そこで提案されたことを実行しましたが、役に立ちませんでした。

私のテスト ファイル (繰り返しますが、個別に呼び出すとどちらも正常に動作しますが、同じテスト パスの一部として実行すると失敗します) は次のようになります。

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;
    });
  });
});
4

2 に答える 2

2

問題はノックではなく、モカフックの実行順序にある​​と思います:

次の例を見てください。

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本体はこれらのフックが呼び出される前に評価されます。各ノックを でラップする必要があります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();
    });
  });

});
于 2017-01-12T21:00:27.120 に答える