Sinon.js spy.called не работает на RPC
Фон
У меня есть сервер, который регистрирует некоторые RPC с помощью перемычки, и тест, который пытается убедиться, что RPC вызываются с использованием sinon.
Код
server.js
"use strict";
const autobahn = require( "autobahn" );
const server = () => {
const open = () => console.log( "Hello world" );
const start = () => new Promise( fulfil => {
const connection = new autobahn.Connection( {
"url": "ws://localhost:8080/ws",
"realm": "realm1"
} );
connection.onopen = session => {
session.register( "server.open", open )
.then(() => fulfil())
.catch(console.log);
};
connection.open();
} );
//removing Object.freeze won't help =(
return Object.freeze({
start,
open
});
};
module.exports = server;
Этот сервер просто подключается к перекладине, а затем регистрирует open
RPC.
Теперь мой контрольный пример. Я использую мокко с чай:
test.js
"use strict";
const expect = require( "chai" )
.expect;
const autobahn = require( "autobahn" );
const sinon = require( "sinon" );
const serverFactory = require( "./server.js" );
describe( "server", () => {
const server = serverFactory();
const crossbar = {
connection: undefined,
session: undefined
};
const connectToCrossbar = () => new Promise( fulfil => {
crossbar.connection = new autobahn.Connection({
"url": "ws://localhost:8080/ws",
"realm": "realm1"
});
crossbar.connection.onopen = session => {
crossbar.session = session;
fulfil();
};
crossbar.connection.open();
} );
before( "start server", done => {
server.start()
.then( connectToCrossbar )
.then( done )
.catch( err => done( err ) );
} );
it( "should open", done => {
const openSpy = sinon.spy( server, "open" );
crossbar.session.call( "server.open", [] )
.then( () => {
expect( openSpy.called ).to.be.true;
done();
} )
.catch( err => done( err ) );
} );
} );
Этот тест открывает соединение с перекладиной, а затем вызывает open
метод на сервере.
проблема
Проблема в том, что хотя я вижу Hello World
console.log, доказывая, что метод был действительно выполнен, мой тест всегда не проходит из-за openSpy.called
всегда false
(хотя метод spied был вызван!).
Что я пробовал
- Удаление
Object.freeze
, Я понимаю, что шпионы и заглушки фактически заменяют функции и объекты, на которые они шпионят, но в этом случае это не помогло. - Используя
stub
вместоspy
, Когда мой шпион не работал, я попытался заменитьopen
метод сstub
и использоватьcallsFake
закончить тест. к несчастьюcallsFake
никогда не кажется, что называется... - С помощью
setTimeout
, Я подумал, что, возможно, причина этого состояла в том, что я делаю тест в ближайшее время, поэтому я создалsetTimeout
с0
развиваяexpect
заявление. Также не удалось.
Вопрос
- Что я делаю неправильно?
- Как я могу это исправить?
2 ответа
отказ
Это решение основано на тестировании и знаниях, которые у меня есть с перекладиной. Если я не прав, пожалуйста, поправьте меня.
Мой вывод
Среди многих других проблем crossbar
один из них - неспособность делать какие-либо тесты. autobahn
будучи библиотекой для crossbar
разделяет эти проблемы.
Причина, по которой мой код не работает, потому что другой процесс на самом деле вызывает мой open
функция вместо моего приложения. Таким образом, процесс, выполняющий тест, никогда не знает, что функция была вызвана.
Решение для этого, чтобы сделать open
функция возвращает результат, а затем проверяет, получим ли мы результат:
it( "should be able to call registered RPCs", done => {
server.getSession().call( "test1", [] )
.then( response => {
expect( response ).to.eql( "Hello World" );
done();
} )
.catch( err => done( err ) );
} );
На самом деле с помощью этого промежуточного программного обеспечения все сложнее проверить... но, по крайней мере, теперь у меня есть способ!
Согласно документации Mocha по тестированию асинхронного кода:
Добавив функцию обратного вызова (обычно с именем done) к it(), Mocha будет знать, что ему следует дождаться вызова этой функции для завершения теста.
Ты никогда не звонишь done()
после expect()
вызов. Поэтому Мокко считает, что ваш тест еще не закончен. Это должно решить вашу проблему
it( "should open", done => {
const openSpy = sinon.spy( server, "open" );
crossbar.session.call( "server.open", [] )
.then( () => {
expect( openSpy.called ).to.be.true;
done(); // You seem to have missed this statement here
} )
.catch( err => done( err ) );
} );