【问题标题】:mock object for document element文档元素的模拟对象
【发布时间】:2014-06-23 02:29:25
【问题描述】:

我有下一个测试代码:

it("Test", function() {
    loadResources();

    expect(document.getElementById('MyElement').innerHTML).toBe("my string");
});

函数体loadResources()

document.getElementById('MyElement').innerHTML = "my string";

我的测试失败并显示以下消息:

TypeError:无法将属性“innerHTML”设置为 null。

看起来我需要为 innerHTML 创建模拟对象。我该怎么做?

【问题讨论】:

    标签: javascript unit-testing jasmine


    【解决方案1】:

    我认为你应该模拟 getElementById 以返回一个虚拟的 HTMLElement

    JASMINE V1.3 或更低版本

    var dummyElement = document.createElement('div');
    document.getElementById = jasmine.createSpy('HTML Element').andReturn(dummyElement);
    

    JASMINE V2.0+

    var dummyElement = document.createElement('div');
    document.getElementById = jasmine.createSpy('HTML Element').and.returnValue(dummyElement);
    

    所以现在,每次调用document.getElementById 都会返回虚拟元素。它将设置虚拟元素的 innerHTML 并最终将其与预期结果进行比较。

    编辑:我猜你应该用toEqual 替换toBetoBe 可能会失败,因为它将测试对象身份而不是值相等。

    EDIT2(关于多个 ID):我不确定,但你可以称之为假的。它将为每个 ID 创建一个新的 HTML 元素(如果它尚不存在)并将其存储在一个对象字面量中以供将来使用(即其他对 getElementById 的调用具有相同的 ID)

    JASMINE V1.3 或更低版本

    var HTMLElements = {};
    document.getElementById = jasmine.createSpy('HTML Element').andCallFake(function(ID) {
       if(!HTMLElements[ID]) {
          var newElement = document.createElement('div');
          HTMLElements[ID] = newElement;
       }
       return HTMLElements[ID];
    });
    

    JASMINE V2.0+

    var HTMLElements = {};
    document.getElementById = jasmine.createSpy('HTML Element').and.callFake(function(ID) {
       if(!HTMLElements[ID]) {
          var newElement = document.createElement('div');
          HTMLElements[ID] = newElement;
       }
       return HTMLElements[ID];
    });
    

    【讨论】:

    • 如果我有 2 个 id 怎么办? document.getElementById('MyElement1').innerHTML = "我的字符串"; document.getElementById('MyElement2').innerHTML = "我的字符串";我需要检查这些身份证吗?
    • 感谢您的精彩回答。这对我帮助很大。
    • 请注意,此答案使用了 jasmine 1.3 语法。 jasmine 2.0(及之后)是不同的。例如:jasmine.createSpy('HTML Element').and.returnValue(dummyElement);
    • @devnull69 您能否澄清一下您示例中的“HTML 元素”应该是通常传递给 document.getElementById 的 ID?
    • 如果我这样做可以重置吗?因为它可能会以某种方式干扰其他规范文件,因为文档是一个全局对象
    【解决方案2】:

    设置文档正文并通过 id 获取元素。我正在使用玩笑,这很好用。 看看这个example from jest documentation

    test('Toggle innerHtml of an element', () =>{
    document.body.innerHTML =
                '<div>' +
                '  <div id="username" >Hello</div>' +
                '  <button id="button" />' +
                '</div>';
    var el = document.getElementById('username');
    var newText = 'new inner text';
    el.innerText = newText;
    expect(el.innerText).toEqual(newText);
    });
    

    【讨论】:

      【解决方案3】:

      试试这个:

      it('should blah', () => {
        const elementMock = {
          innerHTML: 'my string'
        };    
      
        loadResources();
      
        jasmine.spyOn(document, 'getElementById').and.returnValue(elementMock);
      
        expect(document.getElementById('MyElement').innerHTML).toBe('my string');
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-08
        • 1970-01-01
        • 2019-03-29
        • 1970-01-01
        • 1970-01-01
        • 2016-10-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多