我是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版本到另一个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的“描述+代码”模式似乎受到了干扰:
这使我想知道这是否是满足此类测试需求的唯一正确解决方案(或可行吗?)。再次,我对“以正确的方式进行操作”特别感兴趣,而不是使用某种会使它起作用的技巧……在不应该的地方。
答案 0 :(得分:0)
抱歉,没有代码……不确定是否需要,我认为您只需要调整对测试的期望即可。
对于测试的一般规则,您实际上并不关心外部依赖项如何处理服务,您无法控制它。您想测试一下您认为预期的服务结果。
在您的示例中,您只想调用服务的依赖项并调用该函数,然后测试调用enqueue
函数的预期结果。如果返回承诺,请检查成功和错误。它会调用API检查等等。
如果要查看外部依赖项如何使用您的服务,请在这些依赖项测试中对其进行测试。
例如,您有一个调用enqueue
的控制器。在测试中,您必须注入您的提供程序(服务)。并处理期望。