Javascript 如何使用 Karma 和 Jasmine 在 Angular 服务中测试“私有”功能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31013335/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:04:25  来源:igfitidea点击:

How to test 'private' functions in an angular service with Karma and Jasmine

javascriptangularjsunit-testingjasmineangular-services

提问by paniclater

I have a service in my angular app that looks something like this:

我的 angular 应用程序中有一项服务,如下所示:

angular.module('BracketService', []).factory('BracketService', [function() {
    function compareByWeight(a, b) {
        return a.weight - b.weight;
    }
    function filterWeightGroup(competitors, lowWeight, highWeight) {
        //filter stuff
    }
    function createBracketsByWeightGroup(weightGroup) {
        //create some brackets
    }
    //set some base line values
    var SUPER_HEAVY_WEIGHT = 500;
    var SUPER_LIGHT_WEIGHT = 20;
    return {
        //create brackets from a list of competitors
        returnBrackets: function(competitors) {
            var brackets = {};
            //get super light weights
            brackets.superLightWeights = createBracketsByWeightGroup(
                filterWeightGroup(competitors, 0, SUPER_LIGHT_WEIGHT)
                .sort(compareByWeight)
            );
            brackets.superHeavyWeights = createBracketsByWeightGroup(
                filterWeightGroup(competitors, SUPER_HEAVY_WEIGHT, Infinity)
                .sort(compareByWeight)
            );
            brackets.middleWeights = createBracketsByWeightGroup(
                filterWeightGroup(competitors, SUPER_LIGHT_WEIGHT, SUPER_HEAVY_WEIGHT)
                .sort(compareByWeight)
            );
            return brackets;
        }
    };

}]);

I would like to unit test not just the functions / properties that are exposed in the return statement, but also the functions that are outside of the return statement.

我不仅要对 return 语句中公开的函数/属性进行单元测试,还要对 return 语句之外的函数进行单元测试。

My test is currently set up something like this:

我的测试目前设置如下:

describe('BracketService', function() {
    beforeEach(module('bracketManager'));

    it('calling return brackets with no competitors will return 3 empty weight classes', inject(function(BracketService) {
        var mockCompetitors = [];
        var mockBracketResult = {superHeavyWeights: [[]], superLightWeights: [[]], middleWeights: [[]]};
        expect(BracketService.returnBrackets(mockCompetitors)).toEqual(mockBracketResult);
    }));
});

But how do I test the compare, filter and createBrackets functions that are not exposed by the return statement?

但是如何测试 return 语句未公开的 compare、filter 和 createBrackets 函数?

Thanks!

谢谢!

回答by Robert Moskal

There is no way to test those functions. Their scope is the function that comprises your BracketService factory and they are invisible anyplace else. If you want to test them, then you have to expose them somehow.

没有办法测试这些功能。它们的作用域是包含 BracketService 工厂的函数,它们在其他任何地方都不可见。如果你想测试它们,那么你必须以某种方式暴露它们。

You can move them into their own service (which seems like overkill) or you can black box test your BracketService service with enough data combinations to make sure the internal functions are working. That's probably the most sensible approach.

您可以将它们移动到它们自己的服务中(这似乎有点矫枉过正),或者您可以使用足够的数据组合对您的 BracketService 服务进行黑盒测试,以确保内部功能正常工作。这可能是最明智的做法。

If you don't want to put them in a separate service, but still feel the need to test those internal functions, just return them from the factory along with returnBrackets.

如果您不想将它们放在单独的服务中,但仍然觉得需要测试这些内部函数,只需将它们与 returnBrackets 一起从工厂返回即可。

I might do this when I have a number of helper functions that are straight forward to test individually, but open up a combinatorial Pandora's box to black box test. I usually preface such functions with an "_" to show they are helper functions and are only exposed for testing.

当我有许多可以直接单独测试的辅助函数时,我可能会这样做,但是打开组合潘多拉盒子进行黑盒测试。我通常用“_”作为这些函数的前言,以表明它们是辅助函数并且仅用于测试。

return {
    //create brackets from a list of competitors
    returnBrackets: function(competitors) {...},
    _filterWeightGroup: filterWeightGroup,
    _createBracketsByWeightGroup: createBracketsByWeightGroup
   };

回答by taxicala

You will not be able to call those functions without exposing them somehow. But, IMHO, private methods should not have a unit test perse, but be tested at the time the public method that calls them is tested. What you should do is mock the objects that your private function will receive and you will be able to perform expectations on them.

如果不以某种方式公开它们,您将无法调用这些函数。但是,恕我直言,私有方法不应该具有单元测试本身,而是在测试调用它们的公共方法时进行测试。你应该做的是模拟你的私有函数将接收的对象,你将能够对它们执行期望。

回答by Jan

The only way to test them in your current setup is to test the returned function since they're currently local to the scope inside the BracketService. If you want them to be individually testable, you'll need to expose them in the return statement as properties of BracketService.

在当前设置中测试它们的唯一方法是测试返回的函数,因为它们当前位于BracketService. 如果您希望它们可以单独测试,则需要在 return 语句中将它们作为BracketService.