开玩笑手动模拟需要新实例的软件包 [英] Jest manual mocking a package requiring new instance

查看:120
本文介绍了开玩笑手动模拟需要新实例的软件包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Jest手动模拟来模拟所使用的软件包X的行为 在一个项目中.

I'm trying to use Jest manual mock to mock the behaviour of a package X used in a project.

实际应用程序代码中包X的用法如下:

The usage of package X within the the actual application code is like so:

// Real.js

import X from '../lib/X.js';


export default class App  {

  ...

  execute() {
    const x = new X(); // creating a new instance of X
    x.doSomething();   // calling someThing() of X
  }

  ...

}

我的开玩笑的手动模拟来模仿X的行为,如下所示:

my Jest manual mock to mimic the behaviour of X looks like:

global.__test__X = () => ({
  doSomething: jest.fn(async () => console.log('mocked async do something')),
  id: (Math.random() * 1000) % 10,
});

module.exports = global.__test__X;

在我的测试中,我试图查看X被调用了多少次以及使用了哪些参数 使用打击代码:

In my test i'm trying to see how many times X was called and with what parameters using the blow code:

jest.mock('../X');
import Real from '../Real';
const X = require('../X');

describe('Testing...', async () => {
  it('DoSomething should print mocked console statement', async () => {
    Real.execute(); // this would internally call X.doSomething()
    const x = new X();
    console.log(x.doSomething.mock.calls); // gives []

  });
});

在上面,我正在尝试检查X的调用次数,但无法弄清楚是什么 我做错了,因为mock.calls总是[].请注意,模拟正在 如我所见执行mocked async do something.

Using above, I'm trying to check how many times X was called but can't figure out what i'm doing wrong since mock.calls is always []. Note that the mock is getting executed as i can see mocked async do something.

推荐答案

对于jest.mock('./SomeClass'),有完整的解释.适用于这个问题. "ES6类,自动模拟" . 让我们开始吧.

There's a complete explanation for doing this with jest.mock('./SomeClass'); that applies to this question. "ES6 class, Automatic mock" . let's get started.

// ./lib/X.js
export default class X {
  constructor () {
    this.id = '1234567890';
  }

  doSomething = () => {
    return 'Original X';
  }
}

请注意,以上代码从未在测试过程中调用过.

Note, the above code has never been called during the test.

这是我们要测试的资源,我的意思是,在此类中,通过模拟的类或模块创建对象.我们要制作一个假的版本而不是原始的版本.

This is the resource we want to test, what I mean is, in this class create objects by the class or module that is mocked. We want to make a fake version instead of the original.

// Real.js
import X from './lib/X.js';

export default class App  {
  constructor() {
    this.x = new X(); // creating a new instance of X
  }

  execute = () => {
    this.x.doSomething(); // calling someThing() of X
  }
}

接受一个函数,该函数应用作模拟的实现.因此,我们要做的是使用手动模拟(__模拟__文件夹)模拟ES6类.

Accepts a function that should be used as the implementation of the mock. So what we will do is using manual mocks ( __ mocks __ folder) to mock ES6 classes.

// ./__mocks__/lib/X.js
module.exports = jest.fn().mockImplementation(() => {
  return {
    doSomething: jest.fn(() => 'Mocking Original X'),
    id: (Math.random() * 1000) % 10
  }
});

当我们在测试文件上import './lib/X.js'时,现在,为了在不实际访问库的情况下测试此方法(从而创建缓慢而脆弱的测试),我们立即使用模拟'./lib/X.js'模块.

When we import './lib/X.js' on our test file, Now, in order to test this method without actually hitting the library (and thus creating slow and fragile tests), we immediately use the mock the './lib/X.js' module.

// Real.test.js
import X from './lib/X.js';
import Real from './Real';

jest.mock('./lib/X.js'); // // X module is now a mock constructor

describe('Testing', async () => {
  beforeEach(() => {
    // Clear all instances and calls to constructor and all methods:
    X.mockClear();
  });


  it('DoSomething should print mocked correct statement', async () => {
    // Ensure our mockClear() is clearing out previous calls to the constructor
    expect(X).not.toHaveBeenCalled(); 

    const real = new Real();
    expect(X).toHaveBeenCalledTimes(1); // Constructor has been called X.js

    real.execute();

    // mock.instances is available with automatic mocks:
    const mockXInstance = X.mock.instances[0];
    const mockDoSomething = mockXInstance.doSomething;
    expect(mockDoSomething).toHaveBeenCalledTimes(1);
    expect(mockDoSomething.mock.calls[0][0]).toEqual('Mocking Original X');
  });
});

也许这还不足以回答问题,至少可以解释模拟在类似情况下的工作原理

maybe this is not enough to answer, at least this explains how mock works in similar cases

这篇关于开玩笑手动模拟需要新实例的软件包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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