gpt4 book ai didi

unit-testing - 如何使用 $httpBackend 对 angularjs promise 链进行单元测试

转载 作者:行者123 更新时间:2023-12-04 01:49:11 25 4
gpt4 key购买 nike

使用 AngularJS,我正在尝试对一个多次调用 $http 的函数进行单元测试。

我的测试看起来像这样:

it('traverses over a hierarchical structure over multiple chained calls', function() {

myService.traverseTheStuff()
.then(function(theAggregateResult) {
// ...is never fulfilled
});

$httpBackend.flush();
});

其他单调用测试将注册传递给 .then() 的回调,并在我调用 .flush() 时立即执行它。

被测代码看起来像这样。
function traverseTheStuff(){

// This will make a call to $http to fetch some data
return getRootData()

// It is fulfilled at the end of the test when I $httpBackend.flush()
.then(function(rootData){

// Another call to $http happens AFTER $httpBackend.flush()
return getNextLevel(rootData.someReference);
})

// The second promise is never fulfilled and the test fails
.then(function(nextLevel){
return aggregateTheStuff(...);
});
}

对于它的值(value),每个单独的调用都单独进行了单元测试。在这里,我想遍历一棵树,聚合一些数据并进行单元测试 a)promise 链接是否正确连接,b)聚合是否准确。将其展平为单独的离散调用已经完成。

最佳答案

我是测试 Angular 的初学者,但我已经设置了一个 plnkr,它通过一个成功的“第二个”then/promise 调用来测试与你的设置非常相似的设置

http://plnkr.co/edit/kcgWTsawJ36gFzD3CbcW?p=preview

以下代码片段是上述 plnkr 的略微简化版本。

我发现的关键点是

  • 我注意到函数 traverseTheStuff 根本不调用 $http/$httpBackend 。它只使用 $q promises 中定义的函数,所以测试假设使用 $q,并注入(inject)
    var deferred1 = null;
    var deferred2 = null;
    var $q = null;

    beforeEach(function() {
    inject(function(_$q_) {
    $q = _$q_;
    });
    });

    beforeEach(function() {
    deferred1 = $q.defer();
    deferred2 = $q.defer();
    }
  • 要异步调用的函数使用它们的 promise 返回值进行监视/ stub ,其中 promise 是在测试本身中创建的,因此在测试 traverseTheStuff 时不会调用它们的实际实现
    spyOn(MyService,'traverseTheStuff').andCallThrough();
    spyOn(MyService,'getRootData').andReturn(deferred1.promise);
    spyOn(MyService,'getNextLevel').andReturn(deferred2.promise);
    spyOn(MyService,'aggregateTheStuff');
  • 测试中没有对“then”的任何调用,只是对测试中创建的 Promise 进行“解析”,然后是 $rootScope.$apply(),然后在 traverseTheStuff 中实际调用“then”回调,这我们也可以测试被称为
    beforeEach(function() {
    spyOn(deferred1.promise, 'then').andCallThrough();
    });

    beforeEach(function() {
    deferred1.resolve(testData);
    $rootScope.$apply(); // Forces $q.promise then callbacks to be called
    });

    it('should call the then function of the promise1', function () {
    expect(deferred1.promise.then).toHaveBeenCalled();
    });
  • 每个 promise 都必须被解析/$apply-ed 以调用链中的下一个“then”函数。所以。要让测试调用aggregateTheStuff(或者更确切地说,它的 stub ),从getNextLevel stub 返回的第二个promise 也必须被解析:
    beforeEach(function() {
    deferred2.resolve(testLevel);
    $rootScope.$apply(); // Forces $q.promise then callbacks to be called
    });

    it('should call aggregateTheStuff with ' + testLevel, function () {
    expect(MyService.aggregateTheStuff).toHaveBeenCalledWith(testLevel);
    });

  • 以上所有问题的一个问题是,它假定了 $q 和 $rootScope 的某些行为。我理解这样的单元测试不应该做出这样的假设,以便真正只测试一点代码。我还没有弄清楚如何解决这个问题,或者我是否有误解。

    关于unit-testing - 如何使用 $httpBackend 对 angularjs promise 链进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20416403/

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