我正在尝试使用 nock 拦截/模拟我的应用程序中的一些 HTTP 流量以进行测试。我们的应用程序向我们的另一个站点进行身份验证,我需要模仿 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;
});
});
});
最佳答案
我认为问题不在于 nock,而在于你的 mocha hook 的执行顺序:
拿这个例子:
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
主体在调用这些钩子(Hook)之前被评估。您应该将每个诺克包裹在 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();
});
});
});
关于node.js - 如何让 Nock 和 Mocha 一起玩得很好?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41619376/