我正在努力重构我的express-decorator NPM包的克隆。这包括重构先前使用the unit tests完成的AVA。我决定使用Mocha和Chai重写它们,因为我更喜欢它们定义测试的方式。
那么,我的问题是什么?看看这段代码(我将其分解来说明问题):
test('express', (t) => {
@web.basePath('/test')
class Test {
@web.get('/foo/:id')
foo(request, response) {
/* The test in question. */
t.is(parseInt(request.params.id), 5);
response.send();
}
}
let app = express();
let controller = new Test();
web.register(app, controller);
t.plan(1);
return supertest(app)
.get('/test/foo/5')
.expect(200);
});
此代码有效。
这是(基本上)相同的代码,现在使用Mocha和Chai以及多次测试:
describe('The test express server', () => {
@web.basePath('/test')
class Test {
@web.get('/foo/:id')
foo(request, response) {
/* The test in question. */
it('should pass TEST #1',
() => expect(toInteger(request.params.id)).to.equal(5))
response.send()
}
}
const app = express()
const controller = new Test()
web.register(app, controller)
it('should pass TEST #2', (done) => {
return chai.request(app)
.get('/test/foo/5')
.end((err, res) => {
expect(err).to.be.null
expect(res).to.have.status(200)
done()
})
})
})
问题是Mocha忽略了TEST #1
,尽管在测试期间代码的部分运行。我试着console.log
那里的东西,它出现在我希望它出现的Mocha日志中。
那么我该如何让这个测试起作用呢?我的想法是以某种方式将上下文(测试套件)传递给it
函数,但这对Mocha来说是不可能的,或者是它?
答案 0 :(得分:2)
看起来你正在从tape
或类似的测试跑者转向Mocha。您需要显着改变您的方法,因为Mocha的工作方式有很大不同。
tape
和类似的跑步者不需要提前知道套件中存在哪些测试。他们在执行测试代码时发现测试,测试可以包含另一个测试。另一方面,Mocha要求在运行任何测试之前可以发现整个套件。*它需要知道套件中将存在的每个测试。它有一些缺点,因为你不能在Mocha运行测试时添加测试。你不能拥有before
钩子,例如从数据库和创建测试中进行查询。相反,您必须在套件启动之前执行查询。但是,这种做事方式也有一些优点。您可以使用--grep
选项仅选择一部分测试,Mocha将毫无困难地执行此操作。您也可以使用it.only
毫无困难地选择单个测试。最后我查了一下,tape
和它的兄弟姐妹在这方面遇到了麻烦。
所以你的Mocha代码无效的原因是因为你在 Mocha开始运行测试后创建了一个测试。 Mocha不会立即崩溃对你而言,当你这样做时,你得到的行为是不确定的。我已经看到Mocha会忽略新测试的情况,并且我已经看到了以意想不到的顺序执行它的情况。
如果这是我的测试,那我要做的是:
从it
移除对foo
的来电。
修改foo
以简单记录我在控制器实例上关注的请求参数。
foo(request, response) {
// Remember to initialize this.requests in the constructor...
this.requests.push(request);
response.send()
}
让测试it("should pass test #2"
检查控制器上记录的请求:
it('should pass TEST #2', (done) => {
return chai.request(app)
.get('/test/foo/5')
.end((err, res) => {
expect(err).to.be.null
expect(res).to.have.status(200)
expect(controler.requests).to.have.lengthOf(1);
// etc...
done()
})
})
并且会使用beforeEach
挂钩在测试之间重置控制器,以便隔离测试。