如何在指令测试中模拟服务?

如何在指令测试中模拟服务?

问题描述:

我有一个指令,注入的apiService是$ http和其他自定义服务的包装。如何在指令测试中模拟服务?

,当我尝试测试指令,我不知道如何嘲笑服务:

app.directive('coreMenu', ['apiService', function (apiService) { 
return { 
    restrict : 'E', 
    replace  : true, 
    templateUrl : 'Directives/CoreMenu.tpl.html', 
    link: function (scope) { 
     apiService.get({ 
      module: 'Core', 
      route: 'Menu' 
     }).then(function (response) { 
      scope.menuItems = response.data; 
     }, function (response) { 
      // error: no menu available 
     }); 
    } 
    }; 
}]); 

测试:

describe('coreMenu directive', function() { 
var $compile, $rootScope; 

beforeEach(function() { 
    module('AdminTechPortal'); 
    module('CoreLeftMenu.tpl.html'); 

    inject(function (_$compile_, _$rootScope_) { 
     $compile  = _$compile_; 
     $rootScope = _$rootScope_; 
    }); 

it('replaces the element with the appropriate content', function() { 
    var element = $compile("<core-menu></core-menu>")($rootScope); 
    $rootScope.$digest(); 

    expect(element.html()).toContain('id="core-menu"'); 
    }); 
}); 

该测试抛出(这是正常的):

Error: Unexpected request: GET /Core/Menu/

是否有可能使用$ httpbackend模拟apiService而不仅仅是xhr调用?

我在这种情况下,做如下...熊(此方式)有一些工作,如果承诺需要链接,将会失败!

describe('coreMenu directive', function() { 
    var $compile, $rootScope, apiServiceMock; 

    // BIG WARNING: 
    // This beforeEach() block MUST run before using any inject() 
    beforeEach(function() { 
     apiServiceMock = {}; 

     apiServiceMock.get = jasmine.createSpy('apiServiceMock.get').and.callFake(function() { 
      return { // mock the promise 
       then: function(successCb, errorCb) { 
        // keep the callbacks to call them at our convenience 
        apiServiceMock._successCb = successCb; 
        apiServiceMock._errorCb = errorCb; 
       } 
      }; 
     }); 

     module(function($provide) { 
      // override the apiService in the DI container 
      $provide.value('apiService', apiServiceMock); 
     }); 
    }); 

    beforeEach(function() { 
     module('AdminTechPortal'); 
     module('CoreLeftMenu.tpl.html'); 

     inject(function (_$compile_, _$rootScope_) { 
      $compile  = _$compile_; 
      $rootScope = _$rootScope_; 
     }); 
    }); 

    it('replaces the element with the appropriate content', function() { 
     var element = $compile("<core-menu></core-menu>")($rootScope); 
     $rootScope.$digest(); 

     // SAMPLE TESTS 
     expect(apiServiceMock.get).toHaveBeenCalledWith(...); 
     // test success 
     apiServiceMock._successCb(...); 
     expect(...) // things to expect on success 
     // test failure - probably in another it() 
     apiServiceMock._errorCb(...); 
     expect(...) // things to expect on error 
    }); 
}); 
+0

感谢您的解决方案 – CaptainMat

遵循以下步骤:

  1. 加$ httpBackend变量:
var $compile, $rootScope, $httpBackend; 
  1. 进样和分配上beforeEach
  2. inject(function (_$compile_, _$rootScope_, _$httpBackend_) { 
        $compile  = _$compile_; 
        $rootScope = _$rootScope_; 
        $httpBackend = _$httpBackend_; 
    }); 
    
    1. 创建afterEach
    afterEach(function() { 
        $httpBackend.verifyNoOutstandingExpectation(); 
        $httpBackend.verifyNoOutstandingRequest(); 
    }); 
    
    记住,测试的承诺
    1. 测试
    2. it('replaces the element with the appropriate content', function() { 
          $httpBackend.expectGET('/Core/Menu/'); 
          var element = $compile("<core-menu></core-menu>")($rootScope); 
          $httpBackend.flush(); 
          $rootScope.$digest(); // Not sure if still needed 
          expect(element.html()).toContain('id="core-menu"'); 
      }); 
      
    开始=>
开始=>