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 был вызван!).

Что я пробовал

  1. Удаление Object.freeze, Я понимаю, что шпионы и заглушки фактически заменяют функции и объекты, на которые они шпионят, но в этом случае это не помогло.
  2. Используя stub вместо spy, Когда мой шпион не работал, я попытался заменить open метод с stub и использовать callsFake закончить тест. к несчастью callsFake никогда не кажется, что называется...
  3. С помощью setTimeout, Я подумал, что, возможно, причина этого состояла в том, что я делаю тест в ближайшее время, поэтому я создал setTimeout с 0 развивая expect заявление. Также не удалось.

Вопрос

  1. Что я делаю неправильно?
  2. Как я могу это исправить?

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 ) );
} );
Другие вопросы по тегам