【发布时间】:2019-05-08 16:24:18
【问题描述】:
我是 Jasmine 测试的新手,正在寻找一种“最佳实践”来对有状态的 AngularJS 服务进行单元测试。我能找到的大多数教程都侧重于对无状态服务运行原子调用的测试用例。
这很好地匹配了 Jasmine 语法
it("should do something", function(){ expect(target.doSomething()).toBe... })
但是,我发现没有明显的方法可以将此模式扩展到涉及对一个或多个服务函数的多次调用的测试用例。
让我们想象一下这样的服务:
angular.module("someModule").factory("someService", function(){
return {
enqueue: function(item){
// Add item to some queue
}
}
});
对于这样的服务,测试对enqueue() 的连续调用以正确的顺序处理项目是有意义的。这涉及编写一个多次调用enqueue() 并检查最终结果的测试用例(显然不能使用上述简单的服务来实现,但这不是重点……)
什么不起作用:
describe("Some service", function(){
// Initialization omitted for simplicity
it("should accept the first call", function() {
expect(someService.enqueue(one)).toBe... // whatever is correct
});
it("should accept the second call", function() {
expect(someService.enqueue(two)).toBe... // whatever is correct
});
it("should process items in the correct order", function() {
// whatever can be used to test this
});
});
上面的代码(实际上不是定义一个而是三个测试用例)随机失败,因为三个测试用例被执行......就像随机一样。
this thread 中的一位发帖人建议将代码分成几个 describe 块将按照给定顺序执行这些代码,但这似乎又与一个 Jasmine 版本不同(根据其他发帖人相同的线程)。此外,以随机顺序执行套件和测试似乎是预期的方式。即使通过设置可以覆盖此行为,这也可能不是正确的方法。
因此,测试多调用场景的唯一正确方法似乎是使其成为一个测试用例,如下所示:
describe(("Some service", function(){
// Initialization omitted for simplicity
it("should work in my complex scenario", function(){
expect(someService.enqueue(one)).toBe... // whatever is correct
expect(someService.enqueue(two)).toBe... // whatever is correct
expect(/* whatever is necessary to ensure the order is correct */);
});
});
虽然从技术角度来看,这似乎是合乎逻辑的方式(毕竟,复杂的场景是一个测试用例而不是三个),Jasmine “描述 + 代码”模式在这个实现中似乎受到了干扰:
- 无法将消息与测试用例中可能失败的每个“子步骤”相关联;
- 对于单个“它”的描述不可避免地很冗长,就像上面的示例一样,要真正说明复杂场景的有用信息。
这让我想知道这是否是这种测试需求的唯一正确解决方案(或者是它?)。再次,我对“以正确的方式做事”特别感兴趣,而不是使用某种可以使它工作的黑客......在它不应该的地方。
【问题讨论】:
标签: javascript angularjs unit-testing jasmine