我有一个我想测试的java脚本方法。它看起来像这样(这是简化的psudocode,原谅错别字)
$scope.savePerson = function(){
Person.create($scope.person).then(function(newPerson){
if($scope.person.org){
Organization.addPerson($scope.person.org, newPerson.id);
}
toaster.pop('success', "person added");
}
这是使用restangular,但这个想法很简单。当调用savePerson方法时,它首先保存person对象,一旦该保存完成它,然后尝试将该人员保存到组织,如果组织已设置。在人员出现之前,该组织无法保存。
我想通过为个人和组织创建间谍来测试这种逻辑,然后期望它们都被调用。一个天真的方法可能看起来像这样:
describe( 'save person', function () {
var Person, Organization, person;
beforeEach(inject(function($controller, $q, _Organization_, _Person_) {
Person=_Person_;
Organization=_Organization_;
person={...} //whaver goes here, but include an org
Person.create=jasmine.createSpy('create()').andCallFake( funciton(newPerson){
var defer = $q.defer();
defer.resolve(personParam);
return defer.promise;
});
Organization.addPerson= jasmine.createSpy('addPerson()').andCallFake(funciton(personParam){
var defer=$q.defer();
defer.resolve(personParam);
return defer.promise;
});
controllerOptions.Person=Person;
controllerOptions.Organization=Organization;
controllerOptions.person=person;
MyController= $controller('MyController', controllerOptions);
}));
it('adds org if exists', function(){
$scope.savePerson($scope.person);
expect(Person.create).toHaveBeenCalled();
expect(Organization.addPerson).toHaveBeenCalled();
});
这将写入失败,特别是不会调用addPerson。这不是代码中的缺陷,而是线程问题。因为我的代码调用.then on person.create它正在创建一个异步线程来运行。在异步线程启动并运行then逻辑之前,不会调用Organization.addPerson。问题是我的测试在不等待该线程的情况下继续运行,因此它会进入expect调用并失败。
现在一个非常懒的修复方法是在我的测试中添加一个短暂的10毫秒等待。此测试等待异步线程的那一刻将启动,立即获得响应,并调用addPerson。然而,这是关于中断将如何发生的假设的中继,并且不足以进行测试。
我相信我也可以通过让我的origination.addPerson函数设置一些“addPersonCalled”值然后使用仅在设置了addPersonCalled方法时运行的async calls来解决这个问题,但它看起来有点难看。
这似乎是一个常见的用例。我想知道茉莉是否有更清洁的方法来支持这个用例?有没有办法告诉茉莉等待任何当前的事情。那么在继续测试之前,你的承诺要求解决的方法是什么?
答案 0 :(得分:0)
我们有两种选择。第一种是调用$ timeout.flush()或$ rootScope。$ apply()来解决所有的承诺(Testing AngularJS promises in Jasmine 2.0)
然而,这解决了所有承诺,这成为我测试的一个问题,因为我承诺了我还没有想要解决的问题。这部分是由于一些丑陋的黑客可以解决传统程序的问题,这些问题正在逐步消除。
另一个看起来非常有希望的工具(双关语并非故意,诚实!)是模拟承诺:http://pivotallabs.com/testing-javascript-promises/
不幸的是,我还没有使用过该工具,但它看起来很不错。