【问题标题】:How to test local functions within angular controllers?如何在角度控制器中测试本地功能?
【发布时间】:2015-04-19 17:17:20
【问题描述】:

假设我有一个这样的控制器:

angular
    .module("app", [])
    .controller("NewsFeedController", [
        "$scope",
        "NewsFeedService",
        function ($scope, NewsFeedService) {
            $scope.news = [
                { stamp: 1 },
                { stamp: 9 },
                { stamp: 0 }
            ];

            $scope.onScroll = function () {
                /*
                    might do some stuff like debouncing, 
                    checking if there's news left to load, 
                    check for user's role, whatever. 
                */

                var oldestStamp = getOldestNews().stamp;
                NewsFeedService.getOlderThan(oldestStamp);

                /* handle the request, append the result, ... */
            };

            function getOldestNews () {
                /* code supposed to return the oldest news */
            }
        }
    ]);

getOldestNews 被声明为本地函数,因为没有必要在 $scope 中公开它。

我应该如何处理它?我该如何实际测试这个功能?

describe("NewsFeedController", function () {
    beforeEach(module("app"));

    var $controller, $scope, controller;

    beforeEach(inject(function (_$controller_) {
        $controller = _$controller_;
        $scope      = {};
        controller  = $controller("NewsFeedController", { $scope: $scope });
    }));

    it("should return the oldest news", function () {
        // How do I test getOldestNews?
    });
});

顺便说一句,如果该解决方案也适用于服务和指令中的本地函数,那就太好了。


相关问题:

【问题讨论】:

  • 从哪里调用 getOldestNews?如果没有入口点,为什么会存在?
  • @Ricconnect 我在 sn-p 中添加了一些上下文,如果还不清楚,请告诉我。
  • NewsFeedService 上有getOldestNewsItemgetOldestNewsItemStamp 方法不是更合乎逻辑吗?我问这个是因为,如果你想测试私有方法,这在大多数情况下表明设计不好。
  • 好,好点子!所以NewsService.getOldestNews 应该接受一个论点,一个新闻项目的集合?我想知道什么更理想:在服务或$scope 中存储项目。将这些存储在服务本身似乎不是一个好主意,对吧?
  • 我也想知道它是否真的值得成为 NewsService 的方法,因为它可能只对这个特定的控制器有用。

标签: angularjs karma-runner karma-jasmine


【解决方案1】:

现在我看到了您真正想要在代码中执行的操作。我认为没有必要测试私有函数,因为它没有包含足够的逻辑。我建议您只在 NewsFeedService 上创建一个间谍来测试是否将正确的数据发送到该服务。

describe("NewsFeedController", function () {

    beforeEach(module("app"));

    var $controller, $scope, controller;
    var newsFeedServiceMock = jasmine.createSpyObj('NewsFeedService', ['getOlderThan']);

    beforeEach(inject(function (_$controller_) {
        $controller = _$controller_;
        $scope      = {};
        controller  = $controller("NewsFeedController", { $scope: $scope, NewsFeedService : newsFeedServiceMock });
    }));

    it("should return the oldest news", function () {
         $scope.news = [
            { stamp: 76 },
            { stamp: 4 },
            { stamp: 83 }
         ];

         $scope.onScroll();

         expect(newsFeedServiceMock.getOlderThan).toHaveBeenCalledWith(83);
    });
});

这样你可以检查你的 onScroll 方法是否正确的行为,而不需要检查私有方法。您只想测试公共方法,因此您可以灵活地创建私有方法来分离逻辑,而无需更改您的测试。

【讨论】:

  • 如果 pvt 函数有足够的逻辑怎么办.. 无论如何我可以在不更改公共函数的情况下测试它们吗?
  • 如果私有函数中包含这么多逻辑,您可能应该将该私有函数移至单独的角度服务。在单元测试中测试私有函数通常是一种不好的做法。它消除了代码的灵活性。
  • 但是,如果我想在单元测试中测试私有函数怎么办?有没有办法在单元测试中测试私有函数?
  • 不可以在单元测试中测试私有函数,所以你需要将控制器内部的函数暴露出来或者作为公共函数移动到另一个服务中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多