gpt4 book ai didi

angularjs - Angular 单元测试-同一服务中的模拟方法/封闭

转载 作者:行者123 更新时间:2023-12-03 15:02:10 31 4
gpt4 key购买 nike

我目前正在尝试使用SinonJS对我的 angular.service 进行单元测试,但是遇到了一个问题,希望有人可以阐明为什么会发生这种情况。我已经重构了当前的项目以说明当前的问题。

我还提供了DEMO

我有一个服务peopleService:

(function (){

angular.module('myApp')
.factory('peopleService', peopleService);

peopleService.$inject = ['$q'];

function peopleService ($q){
var people = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'];

// in actual project, this makes an http request
function getFamily () {
return people;
}

function getAdults (){
var family = getFamily();
return family.filter(function (person){
return person === 'Homer' || person === 'Marge';
});
}

return {
getFamily: getFamily,
getAdults: getAdults
}
}

}());

在此服务中,我的方法 getAdults使用 getFamily,过滤结果并返回数据。

在我的单元测试中,我试图模拟 getFamily并查看是否正在调用该方法。现在这就是问题所在了……

我尝试的第一件事是暂存该方法并覆盖当前方法,如下所示:
beforeEach(function (){
module('myApp');

inject(function (_peopleService_){
peopleService = _peopleService_; // get the service
sinon.stub(peopleService, 'getFamily'); // stub it
});
});

然后,我去测试 getAdults是否调用 getFamily方法:
it('getAdults should call "getFamily" once', function(){
peopleService.getAdults();
expect(peopleService.getFamily.calledOnce).toBe(true);
});

测试失败,并且未调用 stub 方法...

我调试并发现,尽管该功能实际上已更改:


该服务仍保留对创建该服务时使用的方法的引用(关闭):

我最初的想法是我没有正确地对方法进行 stub 。然后,我尝试使用 $provide ( $provide.value)和 $injector decorator 覆盖该方法,但最终得到了相同的结果(保留在原始方法上的闭包)。

一个解决方案是使用 this:
 function getAdults (){
var family = this.getFamily(); // <-- by using this.getFamily would reference the mock
return family.filter(function (person){
return person === 'Homer' || person === 'Marge';
});
}

但是,我不明白为什么我必须这样做。

简而言之,有谁知道:
  • 如何在同一服务中模拟另一个方法而不必使用this
  • 如何在单元测试
  • 中模拟闭包变量

    非常感谢您的参与。

    最佳答案

    当在对象上 stub 方法时,该对象的属性将被覆盖,而不是其引用的原始函数。

    以下面的代码为例:

    function myFunction () {};
    var myObj = { prop: myFunction };

    myObj.prop === myFunction; // true
    myObj.prop = 'changed';

    typeof myFunction === 'function'; // true
    myObj.prop === myFunction; // false

    更改 myObj.prop不会更改原始功能,但 myFunction仍然存在。但是, myObj.prop丢失了对 myFunction的引用。如果这是在sinon世界中,则 stub 只是将 myObj.prop的引用更改为 stub 对象。

    这就是为什么在服务中测试代码以调用同一服务中的另一个函数时,该代码需要引用该服务返回的同一对象的原因。如果您想避免在所有地方都使用 this关键字,则可以这样构造服务:
    angular.module('myApp')
    .factory('peopleService', peopleService);

    peopleService.$inject = ['$q'];

    function peopleService ($q){
    var service = {
    getFamily: getFamily,
    getAdults: getAdults
    };

    return service;

    function getFamily () {
    // ...
    }

    function getAdults (){
    var family = service.getFamily(); // <-- reference service.getFamily()
    // ...
    }
    }

    关于angularjs - Angular 单元测试-同一服务中的模拟方法/封闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27328444/

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