Angular 1.5.x/Jasmine - 预期间谍已被调用但从未被调用

Angular 1.5.x/Jasmine - Expected spy to have been called but it was never called

POST-编辑:我刚刚解决了这个问题,尽管也许有人有更好的解决方案。我会很快 post 我的解决方案,但如果有人有正确的解决方案,我会接受他们的回答。

我正在将我的应用程序从 1.4 迁移到 1.5,并将我所有的控制器和指令更改为组件。我现在有一个曾经有效但无效的测试,我需要一些指导。

我正在尝试监视服务方法,但根据单元测试,它没有调用。情况并非如此,因为在应用程序 运行 时会进行 API 调用。这是我收到的消息:

这是我的组件文件:

(function(){
    "use strict";

    angular.module("app").component("profileComponent", {
        templateUrl: "/templates/profile.component.html",
        controllerAs: "vm",
        bindings: {
            resolvedUser: "<"
        },
        controller: function(ImageService, $state){
            const vm = this;
            const resolvedUser = this.resolvedUser;

            resolvedUser ? vm.user = resolvedUser : $state.go("404");

            vm.$onInit = function(){
                ImageService.findByName(vm.user.pokemon.name)
                    .then(function(res){
                        vm.user.pokemon.id = res.id;
                        vm.user.pokemon.image = res.sprites.front_default;
                        vm.user.pokemon.type = res.types[0].type.name;
                    })
                    .catch(function(res){
                        vm.user.pokemon.image = "https://www.native-instruments.com/forum/data/avatars/m/328/328352.jpg?1439377390";
                    });
            }

        }
    });
})();

这是我的规范文件中的相关部分。我在测试失败的地方发表了评论:

describe("profile.component", function(){
    var profileComponent, ImageService, $q, $httpBackend, $state, resolvedUser, jazzSpy, IS,
        API = "http://pokeapi.co/api/v2/pokemon/";

    var RESPONSE_SUCCESS = // very large variable I've omitted for brevity.

beforeEach(angular.mock.module("app"));
    beforeEach(angular.mock.module("ui.router"));

    beforeEach(inject(function(_ImageService_, _$q_, _$httpBackend_, _$state_, _$rootScope_){
        ImageService = _ImageService_;
        $q = _$q_;
        $httpBackend = _$httpBackend_;
        $state = _$state_;
        $rootScope = _$rootScope_;
        $rootScope.$new();
    }));

    describe("profileComponent with a valid user and valid Pokemon", function(){

        beforeEach(inject(function(_$componentController_){
            singleUser = { id: 2, name: "Erlich Bachman", email: "erlich@aviato.com", phone: 4155552233, pokemon: { isPresent: true, name: "celebi"}, icon: { isPresent: false, name: null} };
            let bindings = {resolvedUser: singleUser, ImageService: ImageService, $state: $state };
            profileComponent = _$componentController_("profileComponent", { $scope: {} }, bindings);
            profileComponent.$onInit();
        }));

            beforeEach(function(){
                spyOn(ImageService, "findByName").and.callThrough();
            });

            it("should set state to resolvedUser", function(){
                expect(profileComponent.user).toEqual(singleUser);
            });

            it("should expect ImageService to be defined", function(){
                expect(ImageService.findByName).toBeDefined();
            });

            it("should call ImageService.findByName() and return Pokemon icon", function(){

                  expect(profileComponent.user.pokemon.name).toEqual("celebi");

                $httpBackend.whenGET(API + "celebi").respond(200, $q.when(RESPONSE_SUCCESS));
                $httpBackend.flush();

                // This is where the test fails
                  expect(ImageService.findByName).toHaveBeenCalledWith("celebi");
            });
        });

前面提到过,$onInit需要在spyOn之后调用:

beforeEach(function(){
    spyOn(ImageService, "findByName").and.callThrough();
    profileComponent.$onInit();
});