首页 > 解决方案 > 通过 Jest 对复杂对象使用 Spies 和 Mocks

问题描述

我对使用 Jest 为当前未发现的 javaScript 代码库进行测试和编写测试相当陌生。该代码涵盖了一些利基用例,因为它在页面加载期间由浏览器有条件地注入和执行。无论如何,我在模拟自定义对象时遇到问题。这是有问题的功能:

const setEnterpriseCookie = () => {
        // Get the current page uri
        let path = window.location.pathname;

        // Matches all pages containing '/regex_expression'
        if (path.match(/.*\/regex_expression.*/)) {
            window.TOOL.cookie.setCookie(...args);
        }
    };

据我了解,我需要模拟两者window.location.pathname以返回一个字符串,并且我需要模拟window.TOOL.cookie.setCookie()为模拟函数。这是我的测试尝试:

var windowSpy;

describe('Tests for the page-specific-methods.js file', () => {

    beforeEach( () => {
        windowSpy = jest.spyOn(global, 'window', 'get');
    });

    afterEach( () => {
        windowSpy.mockRestore();
    })

    test('Test the page path detecting the enterprise string', () => {
        windowSpy.mockImplementation( () => ({
            location: {
                pathname: '/enterprise/contact',
            },
            TOOL: {
                cookie: {
                    setCookie: jest.fn(),
                },
            },
        }));

        setEnterpriseCookie();
        
        expect(window.TOOL.cookie.setCookie).toBeCalledTimes(1);
        expect(window.TOOL.cookie.setCookie).toHaveBeenLastCalledWith(...args);
    })
});

测试失败,说window.TOOL.cookie.setCookie调用了0次。我已经深入研究了这个过程,发现它window.location.pathname正在按预期执行,因此代码正在输入调用window.TOOL.cookie.setCookie. 我认为问题出在我如何模拟的某个地方window.TOOL.cookie.setCookie,但我无法找到任何帮助来描述如何模拟如此多的方法。

在此先感谢您的帮助!

标签: javascriptunit-testingdommockingjestjs

解决方案


只需使用Object.defineProperty()直接在window对象上定义属性。

例如

index.js

const setEnterpriseCookie = (...args) => {
  let path = window.location.pathname;
  if (path.match(/.*\/enterprise.*/)) {
    window.TOOL.cookie.setCookie(...args);
  }
};

exports.setEnterpriseCookie = setEnterpriseCookie;

index.test.js

const { setEnterpriseCookie } = require('./');

describe('63274598', () => {
  describe('Tests for the page-specific-methods.js file', () => {
    test('Test the page path detecting the enterprise string', () => {
      Object.defineProperty(window, 'location', {
        value: { pathname: '/enterprise/contact' },
      });
      Object.defineProperty(window, 'TOOL', {
        value: {
          cookie: {
            setCookie: jest.fn(),
          },
        },
      });
      setEnterpriseCookie('123');

      expect(window.TOOL.cookie.setCookie).toBeCalledTimes(1);
      expect(window.TOOL.cookie.setCookie).toHaveBeenLastCalledWith('123');
    });
  });
});

单元测试结果:

 PASS  stackoverflow/63274598/index.test.js (13.923s)
  63274598
    Tests for the page-specific-methods.js file
      ✓ Test the page path detecting the enterprise string (4ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       50 |     100 |     100 |                   
 index.js |     100 |       50 |     100 |     100 | 3                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        15.975s

推荐阅读