Geo*_*kov 149 javascript unit-testing mocking jasmine angularjs
我有myService使用myOtherService,它进行远程调用,返回promise:
angular.module('app.myService', ['app.myOtherService'])
.factory('myService', [
myOtherService,
function(myOtherService) {
function makeRemoteCall() {
return myOtherService.makeRemoteCallReturningPromise();
}
return {
makeRemoteCall: makeRemoteCall
};
}
])
Run Code Online (Sandbox Code Playgroud)
为了进行单元测试myService我需要模拟myOtherService,这样它的myService方法返回一个promise.我是这样做的:
describe('Testing remote call returning promise', function() {
var myService;
var myOtherServiceMock = {};
beforeEach(module('app.myService'));
// I have to inject mock when calling module(),
// and module() should come before any inject()
beforeEach(module(function ($provide) {
$provide.value('myOtherService', myOtherServiceMock);
}));
// However, in order to properly construct my mock
// I need $q, which can give me a promise
beforeEach(inject(function(_myService_, $q){
myService = _myService_;
myOtherServiceMock = {
makeRemoteCallReturningPromise: function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
}
};
}
// Here the value of myOtherServiceMock is not
// updated, and it is still {}
it('can do remote call', inject(function() {
myService.makeRemoteCall() // Error: makeRemoteCall() is not defined on {}
.then(function() {
console.log('Success');
});
}));
Run Code Online (Sandbox Code Playgroud)
从上面可以看出,我的模拟的定义取决于myOtherService我必须加载使用makeRemoteCallReturningPromise.此外,注入模拟应该发生$q,应该在之前
inject().但是,一旦我更改了mock的值,它就不会更新.
这样做的正确方法是什么?
dnc*_*253 175
我不确定为什么你做它的方式不起作用,但我通常用这个spyOn功能来做.像这样的东西:
describe('Testing remote call returning promise', function() {
var myService;
beforeEach(module('app.myService'));
beforeEach(inject( function(_myService_, myOtherService, $q){
myService = _myService_;
spyOn(myOtherService, "makeRemoteCallReturningPromise").and.callFake(function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
});
}
it('can do remote call', inject(function() {
myService.makeRemoteCall()
.then(function() {
console.log('Success');
});
}));
Run Code Online (Sandbox Code Playgroud)
还要记住,您需要$digest调用要调用的then函数.请参阅$ q文档的" 测试"部分.
- - - 编辑 - - -
仔细看看你正在做什么之后,我想我在你的代码中看到了问题.在beforeEach,你正在设置myOtherServiceMock一个全新的对象.将$provide永远不会看到这个参考.您只需要更新现有的参考:
beforeEach(inject( function(_myService_, $q){
myService = _myService_;
myOtherServiceMock.makeRemoteCallReturningPromise = function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
};
}
Run Code Online (Sandbox Code Playgroud)
Pri*_*ngh 69
我们也可以直接通过间谍编写茉莉花实现的回复承诺.
spyOn(myOtherService, "makeRemoteCallReturningPromise").andReturn($q.when({}));
Run Code Online (Sandbox Code Playgroud)
对于Jasmine 2:
spyOn(myOtherService, "makeRemoteCallReturningPromise").and.returnValue($q.when({}));
Run Code Online (Sandbox Code Playgroud)
(复制自评论,感谢ccnokes)
Dar*_*ett 13
describe('testing a method() on a service', function () {
var mock, service
function init(){
return angular.mock.inject(function ($injector,, _serviceUnderTest_) {
mock = $injector.get('service_that_is_being_mocked');;
service = __serviceUnderTest_;
});
}
beforeEach(module('yourApp'));
beforeEach(init());
it('that has a then', function () {
//arrange
var spy= spyOn(mock, 'actionBeingCalled').and.callFake(function () {
return {
then: function (callback) {
return callback({'foo' : "bar"});
}
};
});
//act
var result = service.actionUnderTest(); // does cleverness
//assert
expect(spy).toHaveBeenCalled();
});
});
Run Code Online (Sandbox Code Playgroud)
您可以使用像sinon这样的存根库来模拟您的服务.然后您可以返回$ q.when()作为您的承诺.如果scope对象的值来自promise结果,则需要调用scope.$ root.$ digest().
var scope, controller, datacontextMock, customer;
beforeEach(function () {
module('app');
inject(function ($rootScope, $controller,common, datacontext) {
scope = $rootScope.$new();
var $q = common.$q;
datacontextMock = sinon.stub(datacontext);
customer = {id:1};
datacontextMock.customer.returns($q.when(customer));
controller = $controller('Index', { $scope: scope });
})
});
it('customer id to be 1.', function () {
scope.$root.$digest();
expect(controller.customer.id).toBe(1);
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
131377 次 |
| 最近记录: |