我对Angular \ SinonJS有点新意,所以请原谅这个愚蠢的问题,如果这很明显就要忍受。我做了一些谷歌搜索,似乎无法找到答案。我已经使用SinonJs进行模拟,因为这是在Pluralsight视频中推荐的。不确定它是否是最佳选择。任何替代方案都欢迎。
我想测试我的AngularJS控制器的行为,并测试它使用我指定的标准调用我的存储库搜索方法一次。
我的控制器中有以下内容,并且在我的Jasmin测试运行器中出现错误:
目标controller.js:
stepByStepApp.controller("goalController", function ($scope, goalRepository) {
$scope.viewGoalButtonDisabled = true;
$scope.search = function (criteria) {
$scope.errors = [];
return goalRepository.search(criteria).$promise.then(
function (goals) {
$scope.viewGoalButtonDisabled = true;
return goals;
},
function (response) {
$scope.viewGoalButtonDisabled = true;
$scope.errors = response.data;
});
};
});
目标控制器-tests.js
'use strict';
(function () {
describe('Given a Goal Controller', function () {
var scope, controller, goalRepositoryMock, goals, criteria;
beforeEach(function () {
module('stepByStepApp');
inject(function ($rootScope, $controller, goalRepository) {
scope = $rootScope.$new();
goalRepositoryMock = sinon.mock(goalRepository);
goals = [{ foo: 'bar' }];
criteria = 'test search criteria';
controller = $controller('goalController', { $scope: scope });
});
});
it('the View Goal Button should be disabled', function () {
expect(scope.viewGoalButtonDisabled).toBe(true);
});
describe("when a goal is searched for, it", function () {
it("should search the Goal Repository", function () {
goalRepositoryMock.expects('search').once().returns(goals);
scope.search(criteria);
goalRepositoryMock.verify();
});
});
});
}())
我收到以下错误:
2 specs, 1 failure
Given a Goal Controller
when a goal is searched for, it
should search the Goal Repository
TypeError: Cannot read property 'then' of undefined
我显然没有嘲笑对" goalRepository.search(条件)的调用。$ promise.then"正常。我如何正确地模仿$ promise和.then?提前谢谢。
答案 0 :(得分:2)
我假设此存储库正在返回资源对象。话虽如此,这是我将如何测试这个控制器。
这是工作plunk。
你需要嘲笑承诺链。为此,您需要注入$ q服务。以下是我的课前广泛的声明。我使用存根进行模拟。我将那个模拟注入我测试的控制器中。
beforeEach(inject(function($controller, $rootScope, $q) {
q = $q
scope = $rootScope;
goalRepositoryStub = sinon.stub({
search: function() {}
});
testCtrl = $controller("goalController", {
$scope: scope,
goalRepository: goalRepositoryStub
});
}));
通过这个模拟的存储库,我现在可以完全控制它的功能。
在这个区块中,我实际上模拟了整个承诺链。我从q服务中得到一个推迟的对象。从中我得到了承诺。然后我把这个承诺放在一个假的资源对象中。然后,每当调用搜索时,我都会返回该伪资源对象。然后我在范围内调用搜索。
beforeEach(function() {
deferred = q.defer();
promise = deferred.promise;
returnedResource = {
$promise: promise
};
goalRepositoryStub.search.returns(returnedResource);
scope.search(criteria);
});
对于实际测试,您需要告诉延迟对象要做什么(拒绝或解析promise)并触发范围$ apply()函数。然后,您将测试您的代码是否正在执行它应该执行的操作。
以下是我如何测试对goalRepository的成功调用的示例:
describe('successful goalRepository call', function() {
beforeEach(function() {
deferred.resolve(dataToReturn);
scope.$apply();
});
it('should add the data to scope.goals.', function() {
expect(scope.goals).toBe(dataToReturn);
});
it('should not change scope.failureApi to true.', function() {
expect(scope.viewGoalButtonDisabled).toBeFalsy();
});
});
这些不是必要的“最佳实践”或任何其他内容。只是我发现自己解决这个问题的方法。