我试图将测试编码到我的客户端 - 服务器模块。我需要在客户端发送请求之前运行服务器,因此我尝试使用beforeEach
,但测试在服务器开始运行之前就失败了。
我的测试:
'use strict';
const cp = require('child_process');
const ip = require('my-local-ip');
const utils = require('../util/utils');
describe('Server and client connectivity:', () => {
let originalTimeout;
let server;
beforeEach(function() {
server = cp.fork('Server/Server');
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
});
it('should transfer index.html file to client', (done) => {
const client = cp.fork('Client/request', ['-t', ip(), '-p', 3300]);
expect(utils.isFileExistsInDirectory('Client/', 'index.html')).toBe(true);
done();
});
afterEach(function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});
});
当我首先手动运行服务器,然后使用这些命令运行客户端时,它运行正常。
在测试中,有时客户端请求在服务器正在侦听之前发送 。
怎么会发生?
我做错了什么?
答案 0 :(得分:0)
在当前的实施中,您要求服务器进程分叉,但不等待服务器实际启动。
要解决这个问题,我们需要建立一些进程间通信。
如果使用fork
,使用.send
和.on
很容易做到,因为:
返回的ChildProcess将进行额外的通信 内置的通道,允许消息来回传递 父母和孩子之间...
根据the doc。
请参阅示例server.js
:
// A simple server
const express = require('express');
const app = express();
app.get('/', (req, res) => res.json({message: 'ok'}));
app.listen(8080, () => {
// This function exists only if this is a child process
if (process.send) {
// Telling the parent that the server is launched
process.send('launched');
}
console.log('Server started');
});

spec.js
:
const child_process = require('child_process');
const request = require('request');
const assert = require('assert');
describe('Connectivity with forked server', () => {
let server;
beforeAll(done => {
server = child_process.fork('server.js');
// Wait for the message from a child server before running any tests
server.on('message', data => {
if (data === 'launched') {
console.log('Before block executed');
done();
}
});
});
// Killing the server after all the tests
afterAll(() => server.kill('SIGTERM'));
it('should be able to interact with server', done => {
request({url: 'http://localhost:8080', json: true}, (err, resp, body) => {
if (err) {
return done(err);
}
assert.equal(body.message, 'ok');
console.log('test executed');
done();
});
});
});

我已使用beforeAll
和afterAll
代替beforeEach
,但如果需要,您可以切换回beforeEach
。
另外,我已经设置了一些逻辑来在执行测试后关闭进程。