gpt4 book ai didi

javascript - 测试具有要监视的依赖项的 AngularJS 服务

转载 作者:行者123 更新时间:2023-11-29 21:58:42 26 4
gpt4 key购买 nike

在为 mock 依赖创建提供程序时会遇到麻烦,因为它需要使用 $q,这是 Angular 中的另一个服务,而在设置提供程序时无法访问这些服务。

假设我们有一个要测试的工厂:

angular.module('myApp').factory('MyFactory', function (MyDependency, $q) {
return {
doSomething: function () {
var deferred = $q.defer();
MyDependency.doAction().then(function (response) {
deferred.resolve(response);
// other events
}, function (error) {
deferred.reject(error);
// other events
});

return deferred.promise;
}
}
});

以及以下单元测试:

describe('Service: MyFactory', function () {
var myDependency, myFactory;

beforeEach(module('myApp'));

// The problem is here, as $q cannot be instantiated
// when setting up providers, and our mock service we are
// creating as the dependency for MyFactory requires $q
beforeEach(module(function ($provide, $q) {
var promise = $q.defer().promise;
myDependency = jasmine.createSpyObj('MyDependency', ['open']);
myDependency.open.andReturn(promise);
$provide.value('MyDependency', {
doAction: myDependency.open
});
}));

beforeEach(inject(function (MyFactory) {
myFactory = MyFactory;
}));

describe('MyDependency.doAction should be called', function () {
myFactory.doSomething();
expect(myDependency.open).toHaveBeenCalled();
// expect other events
});
});

MyDependency 有一个函数,open,我们需要用我们将控制被解析和拒绝的数据的自定义 promise 来监视和覆盖该方法。我们可以很容易地创建将被注入(inject)到 MyFactory 中的模拟依赖项,但是我们如何在这个阶段访问其他服务,比如 $q

我想出的唯一合理的解决方案是像这样设置提供者,但与 promise.reject() promise.resolve() 相比,它给了我们更少的控制权和更多的解决方法来处理成功与失败

beforeEach(module(function ($provide) {
myDependency = jasmine.createSpyObj('MyDependency', ['doAction']);
myDependency.doAction.andCallFake(function (){
return {
then: function (success, err){
success.call(this);
}
};
});
$provide.value('MyDependency', {
open: myDependency.open
});
}));

最佳答案

假设

  • 我对 MyDependency 服务几乎一无所知
  • 这是 promise
  • 我只能测试解决或拒绝的行为

最奇怪的一行是$provide.value('MyDependency', {});。这是概念验证,欢迎提出任何意见。

实现的第一次修订

(function() {
angular.module('myApp', []).factory('MyFactory', function(MyDependency, $q) {
return {
doSomething: function() {
var deferred = $q.defer();

MyDependency.doAction().then(function(response) {
deferred.resolve(response);
}, function(error) {
deferred.reject(error);
});

return deferred.promise;
}
};
});
})();

describe('myApp', function() {

var MyFactory, MyDependency = {},
$q, scope;

beforeEach(function() {
module('myApp');
});

beforeEach(function() {
module(function($provide) {
$provide.value('MyDependency', {});
});
});

beforeEach(inject(function(_MyFactory_, _$q_, $rootScope) {
MyFactory = _MyFactory_;
$q = _$q_;
scope = $rootScope.$new();
}));

describe('MyDependency', function() {
var MyDependencyDefer;

beforeEach(inject(function(MyDependency, $q) {
MyDependencyDefer = $q.defer();
MyDependency.doAction = jasmine.createSpy('MyDependency.doAction').and.returnValue(MyDependencyDefer.promise);
}));

it('resolves doAction()', function() {
var stubSuccess = 'mock data';
var doSomethingDefer = MyFactory.doSomething();
MyDependencyDefer.resolve(stubSuccess);

doSomethingDefer.then(function(r) {
expect(r).toBe(stubSuccess);
});

scope.$digest();
});

it('rejects doAction()', function() {
var stubError = 'reason error';
var doSomethingDefer = MyFactory.doSomething();
MyDependencyDefer.reject(stubError);

doSomethingDefer.catch(function(r) {
expect(r).toBe(stubError);
});

scope.$digest();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>

实现的第二次修订(经过两年的开发)

(() => {
angular.module('myApp', []).factory('MyFactory', ['MyDependency', MyDependency => {
return {
doSomething: () => MyDependency.doAction()
}
}])
})()

describe('MyFactory.doSomething() returns MyDependency.doAction()', () => {
'use strict';

const promiseResponse = {
succ: 'success',
err: 'error'
}
let MyFactory, MyDependency = {},
$q, scope

beforeEach(module('myApp'));

beforeEach(() => {
module(['$provide', $provide => {
$provide.value('MyDependency', {})
}]);
});

beforeEach(inject(['MyFactory', '$q', '$rootScope', (_MyFactory_, _$q_, $rootScope) => {
MyFactory = _MyFactory_
$q = _$q_
scope = $rootScope.$new()
}]));

describe('MyDependency.doAction() returns promise', () => {
let MyDependencyDefer, doSomethingDefer

beforeEach(inject(['MyDependency', '$q', (MyDependency, $q) => {
MyDependencyDefer = $q.defer()
MyDependency.doAction = jasmine.createSpy('MyDependency.doAction').and.returnValue(MyDependencyDefer.promise)
}]))

beforeEach(() => {
doSomethingDefer = MyFactory.doSomething()
})

it('that can be resolved', done => {
MyDependencyDefer.resolve(promiseResponse.succ)

doSomethingDefer.then(r => {
expect(r).toBe(promiseResponse.succ)
done()
});

scope.$digest()
});

it('that can be rejected', done => {
MyDependencyDefer.reject(promiseResponse.err)

doSomethingDefer.catch(r => {
expect(r).toBe(promiseResponse.err)
done()
})

scope.$digest()
})
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>

关于javascript - 测试具有要监视的依赖项的 AngularJS 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25066943/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com