Sinon.js spy.called没有在RPC上工作

时间:2017-05-24 08:22:09

标签: javascript mocha sinon crossbar autobahnjs

背景

我有一个使用crossbar注册一些RPC的服务器,以及一个试图确保使用sinon调用RPC的测试。

代码

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。

现在我的测试用例。我和chai一起使用摩卡:

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(即使调用了间谍方法!)。

我尝试了什么

  1. 删除Object.freeze。我理解间谍和存根实际上取代了他们正在侦察的功能和对象,但在这种情况下,它没有帮助。
  2. 使用stub代替spy。当我的间谍没有工作时,我尝试用open替换stub方法并使用callsFake完成测试。不幸的是callsFake似乎永远不会被称为......
  3. 使用setTimeout。我想也许发生这种情况的原因可能是我即将进行测试,所以我创建了一个setTimeout 0来演变expect语句。也失败了。
  4. 问题

    1. 我做错了什么?
    2. 我该如何解决?

2 个答案:

答案 0 :(得分:1)

声明

此解决方案基于我对交叉开关的测试和知识。如果我错了,请随时纠正我。

我的结论

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

实际上使用这个中间件一切都比较难测试......但至少现在我有办法了!

答案 1 :(得分:0)

根据testing Asynchronous code上的Mocha文档:

  

通过向它()添加一个回调(通常名为done),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 ) );
} );