簡體   English   中英

Angular js單元測試模擬文檔

[英]Angular js unit test mock document

我正在嘗試測試角度服務,它通過帶有jasmine的$document服務對DOM進行一些操作。 假設它只是將一些指令附加到<body>元素。

這樣的服務看起來像

(function(module) {
    module.service('myService', [
        '$document',
        function($document) {
            this.doTheJob = function() {
                $document.find('body').append('<my-directive></my directive>');
            };
        }
    ]);
})(angular.module('my-app'));

我想像這樣測試它

describe('Sample test' function() {
    var myService;

    var mockDoc;

    beforeEach(function() {
        module('my-app');

        // Initialize mock somehow. Below won't work indeed, it just shows the intent
        mockDoc = angular.element('<html><head></head><body></body></html>');

        module(function($provide) {
            $provide.value('$document', mockDoc);
        });
    });

    beforeEach(inject(function(_myService_) {
        myService = _myService_;
    }));

    it('should append my-directive to body element', function() {
        myService.doTheJob();
        // Check mock's body to contain target directive
        expect(mockDoc.find('body').html()).toContain('<my-directive></my-directive>');
    });
});

那么問題是創建這樣的模擬的最佳方法是什么?

使用真實document測試將使我們在每次測試后清理時遇到很多麻煩,並且看起來不像是一種方法。

我還嘗試在每次測試之前創建一個新的真實文檔實例,但結果卻出現了不同的失敗。

創建一個像下面這樣的對象並檢查whatever變量是否有效但看起來非常難看

var whatever = [];
var fakeDoc = {
    find: function(tag) {
              if (tag == 'body') {
                  return function() {
                      var self = this;
                      this.append = function(content) {
                          whatever.add(content);
                          return self;
                      };
                  };
              } 
          }
}

我覺得我在這里缺少一些重要的東西而且做錯了。

任何幫助深表感謝。

在這種情況下,您不需要模擬$document服務。 使用它的實際實現更容易:

describe('Sample test', function() {
    var myService;
    var $document;

    beforeEach(function() {
        module('plunker');
    });

    beforeEach(inject(function(_myService_, _$document_) {
        myService = _myService_;
        $document = _$document_;
    }));

    it('should append my-directive to body element', function() {
        myService.doTheJob();
        expect($document.find('body').html()).toContain('<my-directive></my-directive>');
    });
});

這里的人物。

如果你真的需要嘲笑它,那么我想你必須按照你的方式去做:

$documentMock = { ... }

但這可能會破壞依賴於$document服務本身的其他東西(例如,使用createElement的指令)。

UPDATE

如果您需要在每次測試后將文檔恢復到一致狀態,則可以按以下方式執行操作:

 afterEach(function() { $document.find('body').html(''); // or $document.find('body').empty() // if jQuery is available }); 

Plunker 在這里 (我必須使用另一個容器,否則Jasmine結果將不會被渲染)。

正如@AlexanderNyrkov在評論中指出的那樣,Jasmine和Karma都有自己的body標簽內容,並通過清空文件體來擦除它們似乎不是一個好主意。

更新2

我已經設法部分模擬了$document服務,因此您可以使用實際的頁面文檔並將所有內容恢復到有效狀態:

 beforeEach(function() { module('plunker'); $document = angular.element(document); // This is exactly what Angular does $document.find('body').append('<content></content>'); var originalFind = $document.find; $document.find = function(selector) { if (selector === 'body') { return originalFind.call($document, 'body').find('content'); } else { return originalFind.call($document, selector); } } module(function($provide) { $provide.value('$document', $document); }); }); afterEach(function() { $document.find('body').html(''); }); 

這里的人物。

我們的想法是用你的SUT可以自由操作的新標簽替換body標簽,並且你的測試可以在每個規格的最后安全地清除。

您可以使用DOMImplementation#createHTMLDocument()創建一個空的測試文檔:

describe('myService', function() {
  var $body;

  beforeEach(function() {
    var doc;

    // Create an empty test document based on the current document.
    doc = document.implementation.createHTMLDocument();

    // Save a reference to the test document's body, for asserting
    // changes to it in our tests.
    $body = $(doc.body);

    // Load our app module and a custom, anonymous module.
    module('myApp', function($provide) {
      // Declare that this anonymous module provides a service
      // called $document that will supersede the built-in $document
      // service, injecting our empty test document instead.
      $provide.value('$document', $(doc));
    });

    // ...
  });

  // ...
});

因為您要為每個測試創建一個新的空文檔,所以不會干擾運行測試的頁面,並且在測試之間的服務之后不必顯式清理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM