gpt4 book ai didi

javascript - AngularJS 中的单元测试 - 模拟服务和 promise

转载 作者:可可西里 更新时间:2023-11-01 01:32:39 24 4
gpt4 key购买 nike

在 Angular 中,一切似乎都有一个陡峭的学习曲线,并且对 Angular 应用程序进行单元测试绝对无法摆脱这种范式。

当我开始使用 TDD 和 Angular 时,我觉得我花了两倍(可能更多)的时间来弄清楚如何测试,甚至更多的时间只是为了正确设置我的测试。但是作为Ben Nadel在他的博客里说了在 Angular 学习过程中有起有落。他的图表绝对是我使用 Angular 的经验。

然而,随着我在学习 Angular 和单元测试方面取得的进步,现在我觉得我花在设置测试上的时间少了很多,而花更多的时间让测试从红色变为绿色——这是一种很好的感觉。

所以我遇到了设置单元测试以模拟服务和 promise 的不同方法,我想我会分享我学到的东西并提出以下问题:

Are there any other or better ways of accomplishing this?

所以在代码上,无论如何我们都来这里是为了什么 - 而不是听一些人谈论他的爱,学习框架的错误成就。

这就是我开始模拟我的服务和 promise 的方式,我将使用 Controller ,但显然可以在其他地方模拟服务和 promise 。

describe('Controller: Products', function () {
var//iable declarations
$scope,
$rootScope,
ProductsMock = {
getProducts: function () {
} // There might be other methods as well but I'll stick to one for the sake of consiseness
},
PRODUCTS = [{},{},{}]
;

beforeEach(function () {
module('App.Controllers.Products');
});

beforeEach(inject(function ($controller, _$rootScope_) {
//Set up our mocked promise
var promise = { then: jasmine.createSpy() };

//Set up our scope
$rootScope = _$rootScope_;
$scope = $rootScope.$new();

//Set up our spies
spyOn(ProductsMock, 'getProducts').andReturn(promise);

//Initialize the controller
$controller('ProductsController', {
$scope: $scope,
Products: ProductsMock
});

//Resolve the promise
promise.then.mostRecentCall.args[0](PRODUCTS);

}));

describe('Some Functionality', function () {
it('should do some stuff', function () {
expect('Stuff to happen');
});
});
});

这对我们来说很有效,但随着时间的推移,我认为一定有更好的方法。一方面,我讨厌

promise.then.mostRecentCall 

事情,如果我们想重新初始化 Controller ,那么我们必须将它从 beforeEach block 中拉出来,并将它单独注入(inject)到每个测试中。

There has to be a better way...

现在我问是否有人有其他方法来设置测试,或者对我选择的方式有何想法或感受?

最佳答案

然后我遇到了另一篇文章、博客、stackoverflow 示例(你选它我可能在那里),我看到了 $q 库的使用。呸!当我们可以使用 Angular 提供的工具时,为什么还要设置一个完整的模拟 promise 。我们的代码看起来更好,看起来更有意义 - 没有丑陋的 promise.then.mostRecent thing

接下来单元测试的迭代是这样的:

describe('Controller: Products', function () {
var//iable declarations
$scope,
$rootScope,
$q,
$controller,
productService,
PROMISE = {
resolve: true,
reject: false
},
PRODUCTS = [{},{},{}] //constant for the products that are returned by the service
;

beforeEach(function () {
module('App.Controllers.Products');
module('App.Services.Products');
});


beforeEach(inject(function (_$controller_, _$rootScope_, _$q_, _products_) {
$rootScope = _$rootScope_;
$q = _$q_;
$controller = _$controller_;
productService = _products_;
$scope = $rootScope.$new();
}));

function setupController(product, resolve) {
//Need a function so we can setup different instances of the controller
var getProducts = $q.defer();

//Set up our spies
spyOn(products, 'getProducts').andReturn(getProducts.promise);

//Initialise the controller
$controller('ProductsController', {
$scope: $scope,
products: productService
});

// Use $scope.$apply() to get the promise to resolve on nextTick().
// Angular only resolves promises following a digest cycle,
// so we manually fire one off to get the promise to resolve.
if(resolve) {
$scope.$apply(function() {
getProducts.resolve();
});
} else {
$scope.$apply(function() {
getProducts.reject();
});
}
}

describe('Resolving and Rejecting the Promise', function () {
it('should return the first PRODUCT when the promise is resolved', function () {
setupController(PRODUCTS[0], PROMISE.resolve); // Set up our controller to return the first product and resolve the promise.
expect('to return the first PRODUCT when the promise is resolved');
});

it('should return nothing when the promise is rejected', function () {
setupController(PRODUCTS[0], PROMISE.reject); // Set up our controller to return first product, but not to resolve the promise.
expect('to return nothing when the promise is rejected');
});
});
});

这开始让人觉得它应该是这样设置的。我们可以模拟我们需要模拟的东西,我们可以设定解决和拒绝的 promise ,这样我们就可以真正测试两种可能的结果。这感觉不错……

关于javascript - AngularJS 中的单元测试 - 模拟服务和 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22830391/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com