【问题标题】:Stencil, Leaflet, unit testing component, gives TypeError: Cannot read property 'deviceXDPI' of undefinedStencil、Leaflet、单元测试组件,给出 TypeError: Cannot read property 'deviceXDPI' of undefined
【发布时间】:2018-12-04 12:15:24
【问题描述】:

所以我们正在开发一个 Stenciljs 组件,它封装了传单地图并添加了一些额外的功能。

现在显然我们不想或不需要测试 Leaflet,而是只测试包装组件中的部分。

因此,使用测试示例,我们创建测试,

import { LeMap } from "./le-map";

describe("Map component tests", () => {
    it("Should build the map component", async () => {
        const map = new LeMap();
        expect(map).not.toBeNull();
    });     
});

尝试加载组件并测试公共功能,但我们得到了

TypeError: Cannot read property 'deviceXDPI' of undefined

> 1 | import {Component, Element, Listen, Method, Prop, Watch} from 
'@stencil/core';
> 2 | import L from 'leaflet';
    | ^
  3 |
  4 | @Component({
  5 |       shadow: false,

我们认为这个消息是因为测试正在尝试渲染传单,并且因为它不是真正的浏览器,所以它无法检测到视图所以抛出这个错误,所以我们试图在测试中模拟传单,但是仍然遇到同样的问题。

我们尝试使用 jest mocking 来模拟传单模块

jest.genMockFromModule('leaflet');

但这并没有什么不同

我唯一的想法是将逻辑与组件分开,但这感觉不对,因为我们这样做只是为了测试。

使用的版本是:传单:1.3.4,@stencil:0.15.2,开玩笑:23.4.2

还有其他建议吗?

感谢@skyboyer 的建议,进一步调查将我带到传单核心 browser.js 文件的这一行

将我带到传单核心 browser.js 文件的这一行

export var retina = (window.devicePixelRatio || (window.screen.deviceXDPI/window.screen.logicalXDPI)) > 1;

但我无法模拟窗口的屏幕属性,因为我收到以下错误

[ts] Cannot assign to 'screen' because it is a constant or a read-only property, 

所以我尝试以下方法。

const screen =  {
    deviceXDPI:0,
    logicalXDPI:0
}

Object.defineProperty(window, 'screen', screen);
Object.defineProperty(window, 'devicePixelRatio', 0);

同样的错误,完全忽略了这一点,所以我尝试忽略导出。

jest.spyOn(L.Browser,'retina').mockImplementation(() => false);

也不开心,所以尝试了

L.Browser.retina = jest.fn(() => false); 

但得到它告诉我它是一个常数并且不能更改(但含义 stats var so ¯_(ツ)_/¯ )

还有什么我可以尝试的吗?

进一步更新, 我设法模拟了窗口,但遗憾的是这并没有解决它。

const screenMock = {            
    deviceXDPI: 0,
    logicalXDPI: 0          
}

const windowMock = {
    value: {
        'devicePixelRatio': 0,
        'screen': screenMock
    }
}
Object.defineProperty(global, 'window', windowMock);

如果我在控制台记录这个,我会得到正确的属性,但是一旦我测试组件的实例化它就会失败

  TypeError: Cannot read property 'deviceXDPI' of undefined

阅读似乎 Leaflet 不检查 DOM 并且只是尝试渲染,无论如何我都看不到这个,我看到了一个没有传单的包,但我不知道如何交换它们只是为了测试。

认为我需要考虑另一种测试策略,可能是量角器。

【问题讨论】:

  • 你可以从 mock 这个方法开始:jestjs.io/docs/en/… 但我不确定你需要 mock 多少个方法来运行测试

标签: unit-testing leaflet jestjs jsdom stenciljs


【解决方案1】:

找到了一个解决方案,尚未完全测试,但测试通过了。 我是通过创建一个

__mocks__ 

与 node_modules 目录处于同一级别的目录。 在其中创建了一个名为 leaflet.js 的文件。它只是一个简单的文件。

'use strict';

const leaflet = jest.fn();

module.exports = leaflet;

然后在我的测试文件(le-map.spec.ts)中我刚刚添加了

jest.mock('leaflet')

导入前

现在我的测试通过了。

我尝试在测试本身中这样做,但这只是给了我同样的错误,它一定是加载序列中的某些东西,这意味着它必须事先手动模拟。

希望这对其他人有所帮助,这让我发疯了好几个星期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 2021-06-25
    • 2018-11-01
    • 2017-08-19
    • 1970-01-01
    • 2017-04-24
    • 2023-03-15
    相关资源
    最近更新 更多