Jon*_*ans 32 javascript jasmine angularjs
我尝试用Jasmine测试我的应用程序并遇到以下问题:
我将根据then我的承诺计算一些东西.这就是我需要测试代码的地方.
这是我的控制器的代码:
TestCtrl.$inject = ["$scope", "TestService"];
/* ngInject */
function TestCtrl($scope, TestService) {
$scope.loadData = function () {
TestService.getData().then(function (response) {
$scope.data = response.data;
$scope.filtered = $scope.data.filter(function(item){
if(item.id > 1000){
return true;
}
return false;
})
});
}
}
Run Code Online (Sandbox Code Playgroud)
我的Jasmine测试代码:
describe('TestService tests', function () {
var $q;
beforeEach(function () {
module('pilot.fw.user');
});
beforeEach(inject(function (_$q_) {
$q = _$q_;
}));
describe('UserController Tests', function () {
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
this.scope = $rootScope.$new();
this.$rootscope = $rootScope;
this.$httpBackend = _$httpBackend_;
this.scope = $rootScope.$new();
var TestServiceMock = {
getData: function () {
var deferred = $q.defer();
var result = [{
"id": 1720,
"user": 1132
},
{
"id": 720,
"user": 132
}, {
"id": 1721,
"user": 1132
}];
deferred.promise.data = result;
deferred.resolve(result);
return deferred.promise;
}
};
this.controller = $controller('TestCtrl', {
'$scope': this.scope,
'TestService': TestServiceMock
});
}));
it('test', function(){
this.scope.loadData();
expect(true).toBeTruthy();
})
});
});
Run Code Online (Sandbox Code Playgroud)
我不明白的奇怪之处是(使用控制台日志测试):
那我怎么能测试then函数里面的代码呢?
感谢帮助
Dus*_*les 41
茉莉花'it'方法采用一个可以调用异步测试的完成参数
it('Should be async', function(done) {
someAsyncFunction().then(function(result) {
expect(result).toBe(true);
done();
});
});
Run Code Online (Sandbox Code Playgroud)
随意尽可能深入,只要确保在一切完成后调用完成.Jasmine的默认超时是每次测试5秒,所以如果没有完成async的话,那么jasmine就会崩溃.您可以在配置中更改此设置或将其设置在终端中.
这直接来自jasmine文档,向您展示如何处理默认超时间隔
describe("long asynchronous specs", function() {
var originalTimeout;
beforeEach(function() {
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
});
it("takes a long time", function(done) {
setTimeout(function() {
done();
}, 9000);
});
afterEach(function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});
});
Run Code Online (Sandbox Code Playgroud)
我认为如果它在10秒内不起作用,你可能会有错误的方法.特别是如果你正在与本地服务器/ db通信.如果您正在执行重大计算,或者正在使用不那么好的互联网连接打外部api,那么这个东西应该只花这么长时间.如果一切都是本地的(或顽固/嘲笑!)那么超过5-10秒的任何东西都是明确的红旗.
你最好看这个https://codecraft.tv/courses/angular/unit-testing/asynchronous/
你实际上有 3 种方法:
1)使用常规它:
it('test', (done) => {
const spy = spyOn(func, 'bar').and.returnValue(Promise.resolve(true));
spy.calls.mostRecent().returnValue.then(res => {
...your expect here...
done();
})
} );
Run Code Online (Sandbox Code Playgroud)
2) 在 beforeEach 中使用 async 和它:
it('test', async(() => {
spyOn(func, 'bar').and.returnValue(Promise.resolve(true));
fixture.whenStable().then(res => {
...your expect here...
})
} ));
Run Code Online (Sandbox Code Playgroud)
3) 如果您没有 Http 或 XHR 调用,请使用 fakeAsync:
it('test', fakeAsync(() => {
spyOn(func, 'bar').and.returnValue(Promise.resolve(true));
tick();
...your expect here...
} ));
Run Code Online (Sandbox Code Playgroud)
希望此解决方案有帮助。我发现测试时有用的一种方法是模拟依赖关系。我试图注释掉我所做的尽可能多的事情。
var returnMock, $scope, TestServiceMock, controller;
beforeEach(module('app'));
beforeEach(inject(function($controller) {
returnMock = {
then: jasmine.createSpy(),
};
$scope = {};
// first assumption is You are testing TestService extensively,
// I don't care about what getData has to do to get results
// All I care about is it gets called when I call loadData
TestServiceMock = {
getData: jasmine.createSpy().and.returnValue(returnMock);
};
controller = $controller;
}));
it('should load data when loadData function is called and result set is
under 1000', function() {
controller('TestCtrl', {
$scope,
TestServiceMock
});
// another assumption is your data comes back in such a format
// perhaps in the actual code check whether data exists and proceed
// or do some other action
var returnedData = {
data: [
{
id: 1,
name: 'item 1',
},
]
}
// when I execute the function/method
$scope.loadData();
// I expect getData to be called
expect(TestServiceMock.getData).toHaveBeenCalled();
// I expect then to be called and the reason is I mocked it
expect(returnMock.then).toHaveBeenCalledWith(jasmine.any(Function));
returnMock.then.calls.mostRecent().args[0](returnedData);
// expect data on scope to be equal to my mocked data
expect($scope.data).toEqual(returnedData.data);
// don't expect any result because 1 < 1000
expect($scope.filtered).toEqual([]);
expect($scope.filtered.length).toEqual(0);
});
it('should load data when loadData function is called and result set is over 1000',
function() {
controller('TestCtrl', {
$scope,
TestServiceMock
});
var returnedData = {
data: [
{
id: 1,
name: 'item 1',
},
{
id: 1000,
name: 'item 1000',
},
{
id: 1001,
name: 'item 1000',
},
{
id: 1002,
name: 'item 1002',
}
]
}
$scope.loadData();
expect(TestServiceMock.getData).toHaveBeenCalled();
expect(returnMock.then).toHaveBeenCalledWith(jasmine.any(Function));
returnMock.then.calls.mostRecent().args[0](returnedData);
expect($scope.data).toEqual(returnedData.data);
// expect a result because some entries in the mocked data have id > 1000
expect($scope.filtered).toEqual([
{
id: 1001,
name: 'item 1000',
},
{
id: 1002,
name: 'item 1002',
}]);
expect($scope.filtered.length).toEqual(2);
});
Run Code Online (Sandbox Code Playgroud)
官方的Jasmine Docs广泛解释了大多数概念。希望解决方案有帮助!!!
| 归档时间: |
|
| 查看次数: |
46859 次 |
| 最近记录: |