如何用业力和茉莉来测试“私人”功能?

时间:2022-08-24 22:30:26

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

我在我的角化应用中有一个服务看起来是这样的:

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和create括弧函数呢?

Thanks!

谢谢!

3 个解决方案

#1


30  

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.

如果您不想将它们放在单独的服务中,但是仍然需要测试这些内部功能,那么只需将它们连同return括弧一起从工厂返回。

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
   };

#2


11  

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.

如果不以某种方式公开这些函数,您将无法调用它们。但是,IMHO认为,私有方法不应该有单元测试,而是在测试调用它们的公共方法时进行测试。您应该做的是模拟您的私有函数将接收到的对象,并且您将能够对它们执行预期。

#3


3  

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的属性公开。

#1


30  

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.

如果您不想将它们放在单独的服务中,但是仍然需要测试这些内部功能,那么只需将它们连同return括弧一起从工厂返回。

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
   };

#2


11  

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.

如果不以某种方式公开这些函数,您将无法调用它们。但是,IMHO认为,私有方法不应该有单元测试,而是在测试调用它们的公共方法时进行测试。您应该做的是模拟您的私有函数将接收到的对象,并且您将能够对它们执行预期。

#3


3  

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的属性公开。