角JS单元测试模拟文件 [英] Angular js unit test mock document

查看:118
本文介绍了角JS单元测试模拟文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想测试的角度服务,通过 $文件做一些操作,以DOM 服务茉莉。
比方说,它只是追加了一些指令到<身体GT; 元素。

I am trying to test angular service which does some manipulations to DOM via $document service with jasmine. Let's say it simply appends some directive to the <body> element.

这样的服务可能看起来像

Such service could look like

(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>');
    });
});

所以,问题是什么是创造这样模拟的最佳方式?

So the question is what would be the best way to create such mock?

与真正的文件测试会给我们带来很多麻烦清理每次测试后,不会看起来像一个路要走。

Testing with real document will give us much trouble cleaning up after each test and does not look like a way to go with.

我也试着每次测试之前创建一个新的真正的文档实例,但结束了不同的故障。

I've also tried to create a new real document instance before each test, yet ended up with different failures.

创建一个对象如下图所示,并检查任何变量的作品,但看起来很丑陋

Creating an object like below and checking whatever variable works but looks very ugly

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

我觉得我失去了一些重要的东西在这里和做一些非常错误的。

I feel that I'm missing something important here and doing something very wrong.

任何帮助很多AP preciated。

Any help is much appreciated.

推荐答案

您不必嘲笑 $文件服务,在这种情况下。它很容易只使用其实际执行情况:

You don't need to mock the $document service in such a case. It's easier just to use its actual implementation:

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>');
    });
});

如果你真的需要模拟出来的话,我想你必须这样做,你做的方式:

If you really need to mock it out, then I guess you'll have to do it the way you did:

$documentMock = { ... }

但是,这可以打破依赖于 $文件服务本身(其他的东西,使用这种指令的createElement ,例如)。

But that can break other things that rely on the $document service itself (such a directive that uses createElement, for instance).

更新

如果您需要将文件恢复到每次测试后一致的状态,你可以做沿着这些路线的内容:

If you need to restore the document back to a consistent state after each test, you can do something along these lines:

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

(我不得不使用另一个容器,否则茉莉花结果将不被渲染)

Plunker here (I had to use another container otherwise Jasmine results wouldn't be rendered).

由于@AlexanderNyrkov在评论中指出,无论是茉莉花和噶有标记中自己的东西,并清空文件身体不擦出来似乎是一个好主意。

As @AlexanderNyrkov pointed out in the comments, both Jasmine and Karma have their own stuff inside the body tag, and wiping them out by emptying the document body doesn't seem like a good idea.

更新2

我已经成功地部分地嘲笑 $文件服务,所以你可以使用实际的页面文件,并恢复所有的一切,以一个有效的状态:

I've managed to partially mock the $document service so you can use the actual page document and restore everything to a valid state:

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可以自由地操纵和测试可以在每个规格年底安然清晰。

The idea is to replace the body tag with a new one that your SUT can freely manipulate and your test can safely clear at the end of every spec.

这篇关于角JS单元测试模拟文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆