【发布时间】:2017-05-12 14:51:54
【问题描述】:
背景
我有一个从机器接收数据的小型服务器。每次收到消息时,我都会调用调度程序对象中的一个函数,该函数只是 console.logs 它接收到的所有内容。
问题
代码运行良好,我可以在控制台中看到console.logs,但Sinon spy.called 不起作用。不管我打多少次dispatcher.onMessage,它总是false。
代码
server.js
const eventDispatcher = {
onMessage: console.log,
};
const server = (dispatcher = eventDispatcher) => {
//this gets called everytime the server receives a message
const onData = data => {
//Process data
//....
dispatcher.onMessage(data);
};
const getDispatcher = () => dispatcher;
return Object.freeze({
getDispatcher
});
};
test.js
describe("message sender", () => {
const myServer = serverFactory();
it("should send information to server", () => {
dummyMachine.socket.write("Hello World!\r\n");
const dataSpy = sinon.spy(myServer.getDispatcher(), "onMessage");
expect(dataSpy.called).to.be.true; //always fails!
});
});
研究
在阅读了类似的帖子后,我认为这是由于某种间接层造成的,如下所示:
并且应该通过使用this来修复:
但是,看着我的代码,我真的无法得到我所缺少的东西。
问题
- 我做错了什么?
MCVE
目录结构
Project_Folder
|____package.json
|____server.js
|____test
|____ dummyMachine_spec.js
package.json
{
"name": "sinon-question",
"version": "1.0.0",
"description": "MCVE about a dummy machine connecting to a server for StackOverflow",
"main": "server.js",
"scripts": {
"test": "NODE_ENV=test mocha --reporter spec --slow 5000 --timeout 5000 test/*_spec.js || true"
},
"author": "Pedro Miguel P. S. Martins",
"license": "ISC",
"devDependencies": {
"chai": "^3.5.0",
"mocha": "^3.3.0",
"sinon": "^2.2.0"
},
"dependencies": {
"net": "^1.0.2"
}
}
server.js
"use strict";
const net = require("net");
const eventDispatcher = {
onMessage: console.log,
};
const server = (dispatcher = eventDispatcher) => {
let serverSocket;
const onData = data => {
//Process data
dispatcher.onMessage(`I am server and I got ${data}`);
};
const start = (connectOpts) => {
return new Promise(fulfil => {
serverSocket = net.createConnection(connectOpts, () => {
serverSocket.on("data", onData);
fulfil();
});
});
};
const stop = () => serverSocket.destroy();
const getDispatcher = () => dispatcher;
return Object.freeze({
start,
stop,
getDispatcher
});
};
module.exports = server;
test/dummyMachine.js
"use strict";
const chai = require("chai"),
expect = chai.expect;
const sinon = require("sinon");
const net = require("net");
const serverFactory = require("../server.js");
describe("Dummy Machine", () => {
const dummyMachine = {
IP: "localhost",
port: 4002,
server: undefined,
socket: undefined
};
const server = serverFactory();
before("Sets up dummyReader and server", done => {
dummyMachine.server = net.createServer(undefined, socket => {
dummyMachine.socket = socket;
});
dummyMachine.server.listen(
dummyMachine.port,
dummyMachine.IP,
undefined,
() => {
server.start({
host: "localhost",
port: 4002
})
.then(done);
}
);
});
after("Kills dummyReader and server", () => {
server.stop();
dummyMachine.server.close();
});
it("should connect to server", done => {
dummyMachine.server.getConnections((err, count) => {
expect(err).to.be.null;
expect(count).to.eql(1);
done();
});
});
it("should send information to server", () => {
dummyMachine.socket.write("Hello World\r\n");
const dataSpy = sinon.spy(server.getDispatcher(), "onMessage");
expect(dataSpy.called).to.be.true; //WORK DAAMN YOU!
});
});
MCVE 说明
- 下载文件并创建指定的目录结构。
- 进入项目文件夹,在终端输入
npm install - 输入
npm test
第一个测试应该通过,这意味着实际上正在建立连接。
第二个测试会失败,即使你得到了控制台日志,证明onMessage被调用了。
【问题讨论】:
-
那么
onMessage会在哪里被调用?在创建间谍和检查它是否被调用之间,我没有看到任何其他代码正在运行。 -
服务器收到数据时,调用onMessage。 console.log 显示,位间谍不起作用...
-
您正在创建间谍并立即检查它是否被调用。 Node.js 不是多线程的,因此这两个操作之间没有上下文切换(即服务器接收任何内容的时间)。
-
这让我很困惑。你是在告诉我,如果我执行 1 秒的
setTimeout然后尝试调用间谍,它会起作用吗? -
它可能,但解决这个问题的正确方法是实现异步测试。但是,您在此处发布的代码无法提供足够的洞察力来确定您的应用程序中的所有内容是如何连接的。例如,
dummyMachine.socket.write()在做什么?考虑创建一个MCVE。
标签: javascript node.js testing sinon