茉莉花间谍电话通过的问题
Issue with jasmine spies call through
我在调用实际实现时遇到问题,我收到此错误:
TypeError: undefined is not an object (evaluating 'GitUser.GetGitUser('test').then') ...
这是我的代码:
app.controller('HomeController', ['$scope', 'GitUser', function ($scope, GitUser) {
$scope.name = "user";
GitUser.GetGitUser('test').then(function (data) {
console.log(data);
if (data) {
$scope.name = data;
}
});
}]);
app.factory('GitUser', function ($http) {
return {
GetGitUser: function (username) {
return $http.get('https://api.github.com/users/' + username)
.then(function success(response) {
return response.data.login;
});
}
};
});
这是我的单元测试:
describe('HomeController Unit Test', function () {
var $controllerConstructor, scope;
beforeEach(module("AngularApp"));
beforeEach(inject(function ($controller, $rootScope) {
$controllerConstructor = $controller;
scope = $rootScope.$new();
}));
it('should test if scope.name is test', function () {
// Act
GitUser = {
GetGitUser: function () { }
};
spyOn(GitUser, "GetGitUser").and.callThrough();
GitUser.GetGitUser();
$controllerConstructor('HomeController', {
'$scope': scope,
'GitUser': GitUser
})
// Assert
expect(GitUser.GetGitUser).toHaveBeenCalled();
expect(scope.name).toBe('test');
});
});
我想你在这里错过了什么
beforeEach(inject(function ($controller, $rootScope, _GitUser) {
$controllerConstructor = $controller;
scope = $rootScope.$new();
GitUser = _GitUser;
}));
这个问题比缺少注入要复杂一些...
这是调整后的测试:
https://plnkr.co/edit/ZMr0J4jmLPtDXKpRvGBm?p=preview
有几个问题:
1) 您正在测试一个 return 承诺的函数 - 因此您还需要以这种方式模拟它(例如使用 return $q.when(..)
)。
2) 您正在尝试测试创建控制器时发生的代码 -
GitUser.GetGitUser('test').then(function (data) {
console.log(data);
if (data) {
$scope.name = data;
}
});
应该改为包装在一个函数中:
function init() {
GitUser.GetGitUser('test').then(function (data) {
console.log(data);
if (data) {
$scope.name = data;
}
});
}
然后在您的范围内提供:
scope.init= init;
然后在您的测试中调用该函数并验证您的断言。如果您不将其包装在一个函数中,它将无法测试。
此外 - 模拟和 callThrough 事情......当你测试控制器(而不是服务)时,你可以使用 callFake 代替 - callFake 函数可以 return 一个带有值的 Promise(一个你想稍后验证的) - 然后你可以确保拼图的控制器部分工作。
var name = 'test';
// instead of trying to mock GitUser you can just callFake and be sure to return a promise
spyOn(GitUser, "GetGitUser").and.callFake(function() {
return $q.when(name);
});
我希望这一切都是有道理的 - plunker 应该把事情说清楚 - 我会在那里添加更多评论。
我在调用实际实现时遇到问题,我收到此错误:
TypeError: undefined is not an object (evaluating 'GitUser.GetGitUser('test').then') ...
这是我的代码:
app.controller('HomeController', ['$scope', 'GitUser', function ($scope, GitUser) {
$scope.name = "user";
GitUser.GetGitUser('test').then(function (data) {
console.log(data);
if (data) {
$scope.name = data;
}
});
}]);
app.factory('GitUser', function ($http) {
return {
GetGitUser: function (username) {
return $http.get('https://api.github.com/users/' + username)
.then(function success(response) {
return response.data.login;
});
}
};
});
这是我的单元测试:
describe('HomeController Unit Test', function () {
var $controllerConstructor, scope;
beforeEach(module("AngularApp"));
beforeEach(inject(function ($controller, $rootScope) {
$controllerConstructor = $controller;
scope = $rootScope.$new();
}));
it('should test if scope.name is test', function () {
// Act
GitUser = {
GetGitUser: function () { }
};
spyOn(GitUser, "GetGitUser").and.callThrough();
GitUser.GetGitUser();
$controllerConstructor('HomeController', {
'$scope': scope,
'GitUser': GitUser
})
// Assert
expect(GitUser.GetGitUser).toHaveBeenCalled();
expect(scope.name).toBe('test');
});
});
我想你在这里错过了什么
beforeEach(inject(function ($controller, $rootScope, _GitUser) {
$controllerConstructor = $controller;
scope = $rootScope.$new();
GitUser = _GitUser;
}));
这个问题比缺少注入要复杂一些... 这是调整后的测试:
https://plnkr.co/edit/ZMr0J4jmLPtDXKpRvGBm?p=preview
有几个问题:
1) 您正在测试一个 return 承诺的函数 - 因此您还需要以这种方式模拟它(例如使用 return $q.when(..)
)。
2) 您正在尝试测试创建控制器时发生的代码 -
GitUser.GetGitUser('test').then(function (data) {
console.log(data);
if (data) {
$scope.name = data;
}
});
应该改为包装在一个函数中:
function init() {
GitUser.GetGitUser('test').then(function (data) {
console.log(data);
if (data) {
$scope.name = data;
}
});
}
然后在您的范围内提供:
scope.init= init;
然后在您的测试中调用该函数并验证您的断言。如果您不将其包装在一个函数中,它将无法测试。
此外 - 模拟和 callThrough 事情......当你测试控制器(而不是服务)时,你可以使用 callFake 代替 - callFake 函数可以 return 一个带有值的 Promise(一个你想稍后验证的) - 然后你可以确保拼图的控制器部分工作。
var name = 'test';
// instead of trying to mock GitUser you can just callFake and be sure to return a promise
spyOn(GitUser, "GetGitUser").and.callFake(function() {
return $q.when(name);
});
我希望这一切都是有道理的 - plunker 应该把事情说清楚 - 我会在那里添加更多评论。