如何在AngularJS工厂方法中模拟对象
我已经创建了一个Angular工厂,该工厂具有处理将代码保存到服务器的方法。其中一个factory方法包含第三方对象,该对象具有执行实际调用的方法。我想测试这段代码,但我无法解决如何模拟第三方对象 用茉莉花测试 我这次测试的目的只是成功地让代码使用我的mock对象,而不是第三方savingUtils对象。可能吗如何在AngularJS工厂方法中模拟对象,angularjs,mocking,angularjs-factory,Angularjs,Mocking,Angularjs Factory,我已经创建了一个Angular工厂,该工厂具有处理将代码保存到服务器的方法。其中一个factory方法包含第三方对象,该对象具有执行实际调用的方法。我想测试这段代码,但我无法解决如何模拟第三方对象 用茉莉花测试 我这次测试的目的只是成功地让代码使用我的mock对象,而不是第三方savingUtils对象。可能吗 var app = angular.module("MyApp", []); app.factory("SavingUtils", function() { return {
var app = angular.module("MyApp", []);
app.factory("SavingUtils", function() {
return {
saveStuff: function() {
if(typeof ThirdPartySavingUtils !== "undefined") {
return ThirdPartySavingUtils.value;
}
}
};
});
这是我的茉莉花测试
describe("Mocking Test", function() {
var ThirdPartySavingUtilsMock;
var SavingUtils;
beforeEach(function() {
angular.mock.module("MyApp", function($provide) {
ThirdPartySavingUtilsMock = {
value: "I am the mock object"
};
$provide.value("ThirdPartySavingUtils", ThirdPartySavingUtilsMock);
});
inject(function(_SavingUtils_) {
SavingUtils = _SavingUtils_;
});
});
it("should run without throwing an exception", function() {
expect(true).toBe(true);
});
it("should mock out ThirdPartySavingUtils with ThirdPartySavingUtilsMock", function() {
var result = SavingUtils.saveStuff();
expect(result).toEqual("I am the mock object");
});
});
你确实有一些选择,但很可能你需要同时做这两件事 1) 您可以创建一个角度服务来包装这个第三方对象——这样您就可以得到一个很好的抽象,以备您需要更改第三方对象时使用 2) 您可以使用类似的模拟框架,它使您能够模拟方法并进行calledOnce等断言 下面是一个使用sinon的模拟测试的链接 您可以基本上看到sinon被用作模拟对象方法的沙箱。Sinon为这些模拟方法提供了额外的属性,因此您可以断言它们是否被调用,调用它们的参数甚至是调用的顺序。它是一个非常非常重要的测试工具
describe('validationManager', function () {
beforeEach(inject(function ($injector) {
sandbox = sinon.sandbox.create();
$rootScope = $injector.get('$rootScope');
$compile = $injector.get('$compile');
$q = $injector.get('$q');
defer = $q.defer();
validator = $injector.get('validator');
validationManager = $injector.get('validationManager');
sandbox.stub(validator, 'makeValid');
sandbox.stub(validator, 'makeInvalid');
sandbox.stub(validator, 'getErrorMessage').returns(defer.promise);
setModelCtrl();
}));
afterEach(function () {
sandbox.restore();
setModelCtrl();
});
it('should be defined', function () {
expect(validationManager).to.exist;
});
describe('validateElement', function () {
it('should return if no $parsers or $formatters on the controller', function () {
validationManager.validateElement(modelCtrl);
expect(validator.makeValid.called).to.equal(false);
expect(validator.makeInvalid.called).to.equal(false);
});
});
编辑-----------------------
在这里,这是对您的代码的实践(我没有运行它,但它给出了一般的想法)
测试
(function (angular, sinon) {
'use strict';
describe('MyApp.SavingUtils', function () {
var sandbox, thirdPartyApi, SavingUtils, thirdPartyApiValue = 2;
beforeEach(inject(function ($injector) {
sandbox = sinon.sandbox.create();
thirdPartyApi = $injector.get('thirdPartyApi');
SavingUtils = $injector.get('SavingUtils');
// stub the method and when called return a simple object or whatever you want
sandbox.stub(thirdPartyApi, 'save').returns({ id: 1});
sandbox.stub(thirdPartyApi, 'value', function () {
return thirdPartyApiValue;
});
}));
afterEach(function () {
// This removes those stubs and replace the original methods/values
sandbox.restore();
});
describe('save', function () {
it('should return call the save method on thirdPartyApi', function () {
var item = {};
SavingUtils.save(item);
expect(thirdPartyApi.save.calledOnce).to.equal(true);
});
});
describe('getValue', function () {
it('should return value of value property on thirdPartyApi', function () {
var result = SavingUtils.getValue();
expect(result).to.equal(thirdPartyApiValue);
});
});
});
}(angular, sinon));
感谢您的回答和示例代码。我将不得不看看Sinon,并尝试用服务包装第三方代码。你能告诉我我尝试的方式有什么问题吗?有没有可能像我尝试的那样模仿那个物体?Thanks@Joe查看编辑-很高兴看到您正在考虑测试!
(function (angular, sinon) {
'use strict';
describe('MyApp.SavingUtils', function () {
var sandbox, thirdPartyApi, SavingUtils, thirdPartyApiValue = 2;
beforeEach(inject(function ($injector) {
sandbox = sinon.sandbox.create();
thirdPartyApi = $injector.get('thirdPartyApi');
SavingUtils = $injector.get('SavingUtils');
// stub the method and when called return a simple object or whatever you want
sandbox.stub(thirdPartyApi, 'save').returns({ id: 1});
sandbox.stub(thirdPartyApi, 'value', function () {
return thirdPartyApiValue;
});
}));
afterEach(function () {
// This removes those stubs and replace the original methods/values
sandbox.restore();
});
describe('save', function () {
it('should return call the save method on thirdPartyApi', function () {
var item = {};
SavingUtils.save(item);
expect(thirdPartyApi.save.calledOnce).to.equal(true);
});
});
describe('getValue', function () {
it('should return value of value property on thirdPartyApi', function () {
var result = SavingUtils.getValue();
expect(result).to.equal(thirdPartyApiValue);
});
});
});
}(angular, sinon));