2017-02-21 26 views
1

У меня есть следующий контроллер в моем угловом приложении.

m = angular.module "myapp.dashboards" 

    m.directive "lkDashboardElement", (
     $timeout 
     MyAppSettings 
    )-> 

     scope: 
     dashboard: "=" 
     element: "=" 
     dashboardController: "=" 
     elementLoaded: "&" 

     link: ($scope, $el)-> 

     if MyAppSettings.shouldCalculateTableWidth 

      document.addEventListener "dashboard.element.rendered", => 

      $timeout(-> 
       .. 
       .. 
      ) 

Я удаляю много вещей, поэтому только важная часть показывает. То, что у меня возникают проблемы, связано с моим использованием Angular $timeout. В настоящее время я проверяю определенное состояние shouldCalculateTableWidth, и если я вижу огонь, я сразу же перехожу.

В настоящее время я пытаюсь написать единичный тест, который проверяет, используется ли $timeout.

Вот мой тест:

describe "in a phantomjs context", -> 
    beforeEach -> 
    # This sets our Phantom rendering context to true for testing purposes 
    MyAppSettings._setIsPhantomRendering(true) 

    afterEach -> 
    MyAppSettings._setIsPhantomRendering(false) 

    it "uses $timeout (instead of applyAsync) for adjusting table widths", -> 
    # Creates a dummy dashboard 
    dashboardController.queryMap = {1: {view: "foo", model: "bar"}} 
    dashboard.elements = [{id: 1}] 
    spyOn($timeout, "flush") 
    expect($timeout.flush).toHaveBeenCalled() 

То, что я пытаюсь сделать, это просто проверить, является ли $timeout используется в этой части кода, так как это важно, как некоторые изображения визуализированы, когда я нахожусь в Phantom (библиотека рендеринга изображения). Когда я запускаю тест, я получаю следующее сообщение об ошибке:

Expected spy flush to have been called. 

Конкретная проблема у меня в следующие две строки в моем тесте:

spyOn($timeout, "flush") 
expect($timeout.flush).toHaveBeenCalled() 

Прежде всего, я не верю, я вызываю правильный метод для $timeout. В моем контроллере очень ясно, я звоню $timeout, а не $timeout.flush. Во-вторых, для Jasmine Spys вы не можете просто spyOn$timeout, так как ему нужна ссылка на класс и метод.

Так что я не совсем уверен, как двигаться дальше. Буду признателен за любую помощь - спасибо!

+0

'flush' - это метод, который существует только в' ngMock', который вызывается из тестов. Таким образом, шпионаж на флеш только проверки, чтобы увидеть, что вы вызвали его из теста. Это ваш тест, вы знаете, что вы это сделали, но почему бы вам не проверить его? –

ответ

1

Когда вы пишете модульный тест, вам необходимо позвонить $timeout.flush(), а затем позвонить $timeout.verifyNoPendingTasks();.

verifyNoPendingTasks() будет генерировать исключение, если есть ожидающие ожидания таймауты, поэтому в основном вы можете утверждать, что исключение никогда не выбрасывается, как expect(function() {$timeout.verifyNoPendingTasks()}).not.toThrow(). Кроме того, вы можете написать ожидание как expect(function() {$timeout.flush()}).toThrow()

Если в контроллере $timeout имеет фиксированное время как $timeout(function() {}, 1000), то в тестовом модуле вы можете flush в $timeout.flush(1000).

Вы можете узнать больше на странице here.

Кроме того, вы можете ознакомиться с приведенным ниже примером рабочего процесса CodePen.

+0

Эй, спасибо Гаураву! Нужно ли мне шпионить за чем угодно? Или я предполагаю называть '$ timeout.flush()', а затем проверить ожидания? – theGreenCabbage

+0

Когда вы вызываете '$ timeout.flush()', он очищает все '$ timeout()', что означает в вашем тесте, вы можете написать утверждение как-то вроде 'expect (function() {$ timeout.verifyNoPendingTasks()}). not.toThrow() '. – Gaurav

+0

И нет, вам не нужно шпионить за чем-либо, поскольку «$ timeout» - это издеваемый объект службы, предоставляемый 'ngMock' в вашем модульном тесте. – Gaurav

0

Если вы хотите шпионить за $ timeout, вам нужно на самом деле replace it в вызове module.decorator со шпионом. Но вы можете спросить себя, действительно ли имеет смысл микрокредитовать внутреннюю часть вашей директивы до такой степени.