我是Jasmine的新手。我试图让我的工厂承诺解决,但它似乎永远不会。
这是我的工厂,它将重新列出公司名单
angular.module('commercial.factories').factory('companyFactory', companyFactory);
function companyFactory($http, $location, sessionStorage, config) {
function getCompanies() {
//call service and include company identifier in the service url
return $http.get(wunUtils.constants.serviceBaseUrl + 'myCompanyService.svc/companies')
.then(function(response) {
return response.data;
}, function(err){
console.log(err);
});
}
});
和我的规范
describe('company', function() {
beforeEach(module('mockedCommercial'));
var $httpBackend, companyFactory, $rootScope
beforeEach(function() {
inject(function(_$httpBackend_, _$rootScope_, _companyFactory_) {
$rootScope = _$rootScope_;
$httpBackend = _$httpBackend_;
companyFactory = _companyFactory_;
});
})
it('should return available languages asynchronously', function() {
$httpBackend.expectGET(/https:\/\/myDomain.com\/myCompanyService.svc\/companies+/)
.respond(function(method, url, data, headers, params) {
var response = {
"data": [{
"address1": "Portsmouth",
"address2": null,
"city": "Portsmouth",
"contactEmail": "mocks@mocks.com",
"contactFirstName": "Mock",
"contactLastName": "Data",
"contactPhone": null,
"contactTitle": "Mr",
"country": "UK",
"fax": null,
"identifier": "c1xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"location": "Portsmouth, UK",
"name": "Mock Company 1",
"phone": null,
"state": "Hampshire",
"zipCode": "PO19 3 EN"
}, {
"address1": "Portsmouth",
"address2": null,
"city": "Portsmouth",
"contactEmail": "mocks@mocks.com",
"contactFirstName": "Test",
"contactLastName": "Test",
"contactPhone": null,
"contactTitle": "Mrs",
"country": "UK",
"fax": null,
"identifier": "c2xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"location": "Portsmouth, UK",
"name": "Mock Company 2",
"phone": null,
"state": "Hampshire",
"zipCode": "Po9 3EN"
}],
"total": 2
}
});
//--------------------------
$rootScope.$digest();
companyFactory.GetCompanies().then(function(result) {
expect(result.hasOwnProperty('total')).toBe(true);
})
});
});
正如你所看到的,我正在使用$ rootScope。$ digest运行承诺,但是我的期望从未被击中,所以测试总是通过。
我已阅读大量关于此事的不同帖子,他们都说这应该有效。我在这里做错了什么还是我错过了一些步骤?
所以我在看了一些更多的帖子后稍微简化了我的问题
这是我的新控制器电话......
$scope.companies = [];
var GetCompanies = function(options) {
companyFactory.GetCompanies().then(function(response) {
options.success(response);
$scope.companies = response
});
}
$scope.GetCompanies = GetCompanies
我的工厂......
function getCompanies() {
//call service and include company identifier in the service url
return $http.get(wunUtils.constants.serviceBaseUrl + 'CompanyService.svc/companies')
.then(function(response) {
return response.data;
}, function(err){
console.log(err);
});
}
var service = {
AddCompany: addCompany,
GetCompany: getCompany,
GetCompanies: getCompanies,
GetUserCompanyFleets: getUserCompanyFleets,
EditCompany: editCompany
};
和我的新规格
describe('company', function() {
beforeEach(module('mockedCommercial'));
var $httpBackend, companyFactory, $rootScope, createController, scope
beforeEach(function() {
inject(function($controller, _$httpBackend_, _$rootScope_, _companyFactory_) {
$rootScope = _$rootScope_;
$httpBackend = _$httpBackend_;
scope = _$rootScope_.$new();
companyFactory = _companyFactory_;
createController = function() {
return $controller('ManageCompaniesController', {
'$scope': scope
});
};
});
})
it('should return available languages asynchronously', function(done) {
$httpBackend.whenGET(/https:\/\/myDomain.com\/V3_Fleet\/CompanyService.svc\/companies+/)
.respond(function(method, url, data, headers, params) {
return [{ 'id': 1 }];
}
});
//--------------------------
var dummy = [{ 'id': 1 }];
createController();
scope.GetCompanies()
$httpBackend.flush()
expect(scope.companies).toEqual(dummy)
scope.$digest(); done()
});
});
答案 0 :(得分:0)
在评估测试期望之前尝试使用$httpBackend.flush()
。
这是angular推荐的方法。有关更多详细信息和示例,请查看documentation here。
答案 1 :(得分:0)
测试异步代码时有两种选择。
这包括:
$httpBackend
$timeout.flush()
$interval.flush()
scope.$apply()
处理剩余的承诺在所有这些之后,你仍然不能完全确定所有待处理的任务都已经处理完毕,尽管它在99.9%的时间内已经足够了。
在这里,您必须确保每个异步控制器方法都返回一个promise,即使返回的promise未在应用程序中使用。它们将用于测试。
Jasmine使异步测试非常困难,但并非不可能。您必须使用done
callback,并对每个异步块进行编码,如:
it('should...', function(done) {
$q.when().then(function() {
return $controller.GetSomething();
}).then(function() {
expect(scope.companies).toEqual(dummy);
}).then(done, done.fail);
});
Mocha handles proper asynchronous functions所以你可以不用done
写一下:
it('should...', function() {
return $q.when().then(function() {
return $controller.GetSomething();
}).then(function() {
expect(scope.companies).toEqual(dummy);
});
});
如果你有工具集,甚至可以使用async-await
:
it('should...', async () => {
await $controller.GetSomething();
expect(scope.companies).toEqual(dummy);
});
答案 2 :(得分:0)
所以经过多次阅读后,我通过简化一切来找到答案。我认为我的问题来自混合 $ httpBackend.flush()和完成()功能
似乎发生的事情是done()函数触发了自己的摘要,因此在尝试使用flush()函数时会发生冲突。
这是我的工厂。它与我原来的有点不同,因为这是一个更简单的功能(更少的东西出错)
function getUser(userId) {
//call service and include user identifier in the service url
return $http.get(wunUtils.constants.serviceBaseUrl + 'myService.svc/fleetusers/' + userId)
.then(function(response) {
return response.data;
});
}
var service = {
GetMe: getMe,
GetUser: getUser,
AddUser: addUser,
EditUser: editUser,
ActivateUser: activateUser
};
这是我的简化规范调用$ httpBackend.Flush()
describe('Testing httpBackend', function() {
var $httpBackend;
beforeEach(module('mockedCommercial'));
beforeEach(inject(function(_$httpBackend_) {
$httpBackend = _$httpBackend_;
}))
it('should behave...', function() {
inject(function(userFactory, $rootScope) {
var mockData = [];
$httpBackend.expectGET(wunUtils.constants.serviceBaseUrl + 'FleetUserService.svc/fleetusers/10').respond(mockData);
var promise = userFactory.GetUser(10);
$httpBackend.flush();
promise.then(function(result) {
expect(result).toEqual(mockData);
});
});
});
});
修改强>
还应该注意,在测试HTTPBackend时,测试只能在使用expectGET和expectPOST时使用,而不是在whenGET和whenPOST时使用。
从我所看到的,whenGet用于模拟数据而expectGet用于测试模拟