【问题标题】:Sinon.js spy.called not working on RPCsSinon.js spy.call 不在 RPC 上工作
【发布时间】:2017-05-24 08:22:09
【问题描述】:

背景

我有一个使用 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。

现在是我的测试用例。我正在将 mocha 与 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。当我的间谍不起作用时,我尝试用stub 替换open 方法并使用callsFake 完成测试。不幸的是,callsFake 似乎从未被称为...
  3. 使用setTimeout。我想可能发生这种情况的原因是我很快就会进行测试,所以我创建了一个 setTimeout0 演变 expect 声明。也失败了。

问题

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

【问题讨论】:

  • const openSpy = sinon.spy( server, "open" ); 是它坚持的地方。您正试图监视服务器中名为 openfunction,而服务器中没有名为 openfunction,这使得 openSpy 始终为 false
  • 是的,有:const open = () => console.log( "Hello world" );。 console.log 甚至可以打印出来!
  • 函数在函数内部。没看到,你试过用const openSpy = sinon.spy( server, "server.open" );打电话给它吗?
  • 我测试过了,也失败了=(
  • 您是否也尝试过测试将open 置于server 函数之外或将hello world 替换为return true

标签: javascript mocha.js sinon crossbar autobahnjs


【解决方案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 ) );
} );

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

【讨论】:

    【解决方案2】:

    根据testing Asynchronous code 上的 Mocha 文档:

    通过给 it() 添加一个回调(通常命名为 done),Mocha 会知道它应该等待这个函数被调用来完成测试。

    expect() 调用之后,您永远不会调用done()。因此 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 ) );
    } );
    

    【讨论】:

    • 问题不在于。我什至没有那么远。问题是断言失败了,它不应该!
    • 哦。你能和堆栈跟踪一起分享失败吗?另外,您尝试过我的解决方案吗?
    • 它失败了,因为它期望 false 为真。我会尽快尝试!
    • 不,没有任何变化!
    • 好的。如果您可以分享我如何设置它来进行一些调试,也许我可以提供帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    相关资源
    最近更新 更多