Javascript 如何在Jasmine+;因果报应单元测试?
因此,我目前正在用Jasmine+Karma测试AngularJS中的一个函数。我正在尝试创建一个对象,并查看它是否已成功添加到数据库中。这个函数调用另一个异步函数,我在测试中似乎无法解释这一点。我知道它从未被呼叫过,因为我没有从它那里得到任何回报。没有控制台日志、错误或任何内容。到目前为止,我有一个名为StoringService的服务,看起来像:Javascript 如何在Jasmine+;因果报应单元测试?,javascript,angularjs,unit-testing,karma-runner,karma-jasmine,Javascript,Angularjs,Unit Testing,Karma Runner,Karma Jasmine,因此,我目前正在用Jasmine+Karma测试AngularJS中的一个函数。我正在尝试创建一个对象,并查看它是否已成功添加到数据库中。这个函数调用另一个异步函数,我在测试中似乎无法解释这一点。我知道它从未被呼叫过,因为我没有从它那里得到任何回报。没有控制台日志、错误或任何内容。到目前为止,我有一个名为StoringService的服务,看起来像: myApp.service("StoringService", function($http){ // Stores my object
myApp.service("StoringService", function($http){
// Stores my object
this.store = function(object,success,error){
var request = {
method: "post",
url: "example.com",
headers: {/*...*/},
data: object.toJSON()
};
$http(request).then(
function(response){
console.log("Success! Yay!");
success(response.data.url.script);
},function(response){
console.log("Error! Bummer...");
error(response);
}
);
};
});
我正在测试的主控制器是我的CreationController。它有一个名为Submit的函数,该函数调用上述服务。这在运行应用程序时有效,但在运行测试时似乎无效。submit方法(CreationController内部)如下所示:
myApp.controller("CreationController", ["$scope","StoringService",
function($scope,StoringService){
$scope.newObject = new Object();
$scope.successAlert = false; // changed by success() in StoringService
$scope.errorAlert = false; // changed by error() in StoringService
$scope.submit = function(){
StoringService.store($scope.newObject,
function(message){
console.log(message);
},
function(error){
console.log(error);
}
);
}
}]);
最后,当我进行Jasmine+Karma测试时,我注意到我的对象没有被创建,经过进一步的检查,我的StoringService在实际的$http请求之前工作正常(示例代码中的第11行)。我不完全确定如何触发这一行动。这就是目前我的测试的样子
//creation_test.js
var scope, service;
describe('Creation Test', function(){
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
beforeEach(module('MyApplication'));
beforeEach(inject($rootScope, $controller, $injector){
scope = $rootScope.$new();
service = $injector.get('StoringService');
$controller('CreationController',{
$scope: scope,
StoringService: service
});
}));
// Fails but should pass
it('should create an object',function(done){
scope.newObject.name = "new_object";
scope.newObject.data = "object data";
scope.submit();
setTimeout(function(){
expect(scope.successAlert).toBe(true);
expect(scope.errorAlert).toBe(false);
done();
},5000);
});
afterEach(function(){
jasmine.DEFAULT_TIMEOUT_INTERVL = originalTimeout;
});
);
我不完全确定这为什么不起作用,或者如何确切地修复它。successAlert和errorAlert的值从未更改,这使我相信$http请求从未被调用。我一直在尝试可能的解决方案,但到目前为止,还没有解决这个问题。如果有人能帮我解决这个问题,我将不胜感激。这里是一个有效的例子。下面的测试确保您正在使用args调用服务方法
expect(loginService.authenticate).toHaveBeenCalledWith({
user: 'david@yahoo.com',
pass: '123'
});
我已经调整了你的测试。当进行单元测试时,我们不想花时间调用后端,这就是为什么我们需要模拟HTTP调用。当您的
store
方法返回承诺时,我们在单元测试中模拟此行为,创建一个我们可以控制的延迟承诺。稍后,您可以解决
或拒绝
测试成功与错误的承诺。我希望有帮助
describe('Controller: CreationController', function() {
beforeEach(module('MyApplication'));
var storingService;
var deferred;
// Mock services and spy on methods
beforeEach(inject(function($q, StoringService) {
deferred = $q.defer();
storingService = StoringService;
spyOn(storingService, 'store').and.returnValue(deferred.promise);
}));
var CreationController;
var scope;
// Initialize the controller and a mock scope
beforeEach(inject($rootScope, $controller) {
scope = $rootScope.$new();
CreationController = $controller('CreationController', {
$scope: scope,
StoringService: storingService
});
}));
it('should create an object', function() {
scope.submit();
scope.$apply(function() {
deferred.resolve();
});
expect(scope.successAlert).toBe(true);
expect(scope.errorAlert).toBe(false);
});
);
你想测试什么?我没有看到
CreationController
创建任何对象……我只是尝试测试对象是否成功地进入数据库。我遗漏了那个代码,因为我不知道是否有必要。但是一个空白对象看起来就像对象{name:,data:,timestamp:}。使用表单,用户将填写姓名和数据字段并提交到数据库。您尝试做的是e2e测试,这通常不需要在Karma中执行。角度单元测试假定不执行任何实际请求。应该有两个测试-一个用于模拟服务的控制器单元,另一个用于模拟$http响应的服务单元。单元测试测试单个单元,因此得名。它们不是“一体式”测试。