5

背景

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

代码

服务器.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;

该服务器简单地连接到交叉开关,然后注册openRPC。

现在我的测试用例。我正在使用带有 chai 的 mocha:

测试.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 Worldconsole.log,证明该方法实际上已执行,但我的测试总是失败,因为 openSpy.called总是false(即使调用了 spied 方法!)。

我试过的

  1. 删除Object.freeze. 我知道间谍和存根实际上替换了他们正在监视的函数和对象,但在这种情况下,它没有帮助。
  2. 使用 astub而不是spy. 当我的间谍不起作用时,我尝试用opena 替换该方法stub并使用callsFake来完成测试。不幸的是callsFake,似乎从来没有被称为...
  3. 使用setTimeout. 我想可能发生这种情况的原因是我很快就会进行测试,所以我创建了一个 setTimeout不断0发展的expect声明。也失败了。

问题

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

2 回答 2

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

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

于 2017-06-02T13:34:28.963 回答
0

根据有关测试异步代码的 Mocha 文档:

通过向 it() 添加回调(通常命名为 done),Mocha 将知道它应该等待调用此函数以完成测试。

你永远不会在通话done()expect()打电话。因此 Mocha 认为您的测试尚未完成。这应该可以解决您的问题

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 ) );
} );
于 2017-05-27T12:57:33.400 回答