Как сделать так, чтобы Нок и Мокка хорошо играли вместе?
Я пытаюсь использовать nock, чтобы перехватить / смоделировать некоторый HTTP-трафик в моем приложении для целей тестирования. Наше приложение аутентифицируется на другом из наших сайтов, и мне нужно nock для имитации HTTP 200 (с данными JSON) и HTTP 401 (без данных) для проверки поведения, когда пользователь вошел или не вошел в систему (соответственно),
У меня есть два теста, которые оба работают правильно, когда запускаются в одиночку, но если я запускаю весь набор тестов, один из них всегда дает сбой. Я понимаю, что nock является общим состоянием, потому что он изменяет, как сам node.js обрабатывает сетевой трафик, и я предполагаю, что это является причиной состояния гонки, но я не могу быть единственным человеком, который когда-либо использовал два разных перехватчика nock для одного и того же запроса в два разных теста, так что я знаю, что что-то упустил.
Может кто-нибудь помочь мне понять, почему эти тесты наступают друг на друга?
Мой вопрос связан с тем, как повторно протестировать один и тот же URL, используя Mocha и 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;
});
});
});
2 ответа
Я думаю, что проблема не в nock, а в том, что касается порядка выполнения вашего мокко-хука:
Возьмите этот пример:
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();
});
});
});
Я использовал ответ Санкет-Катты, который я дал за решение, но немного изменил 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()
звонок никогда не будет достигнут, и поэтому я получу сообщение о том, что время теста истекло, а не конкретный сбой.