Jest.js 如何测试一个在mocked依赖项上使用instanceof的方法

cnwbcb6i  于 6个月前  发布在  Jest
关注(0)|答案(4)|浏览(102)

我有一个typeguard,它检查依赖项的示例。

private isObjectOfA(obj: A | B ): obj is A {
    return obj instanceof A;
  }

字符串
在spec文件中,我已经模拟了A类。

jest.mock('./my-package/a', () => {
  return {
    A: jest.fn().mockImplementation(() => {
      return {
        someMethod: jest.fn()
      };
    })
  };
});

import { A } from './my-package/a';


现在在测试过程中,isObjectOfA总是返回false(因为在测试中,obj的示例返回为“Object”而不是“A”。可能是由于模拟??)。有什么方法可以克服这个问题吗?创建对象的代码如下所示:

this.myObj = someCondition ? new A() : new B();

a7qyws3x

a7qyws3x1#

为了通过instanceof检查,需要建立原型链,例如使用Object.create

jest.mock('./my-package/a', () => {
  const ActualA = jest.requireActual('./my-package/a');

  return {
    A: jest.fn().mockImplementation(() => {
      const a = Object.create(ActualA.prototype);
      return Object.assign(a, { someMethod: jest.fn() });
    })
  };
});

字符串
类自动模拟也将为模拟提供正确的原型链。

gupuwyp2

gupuwyp22#

由于我不想依赖于mock之外的任何东西,所以我基于@estus-flask的解决方案如下:

jest.mock('./module-to-mock', () => {
    const mockClass: jest.MockedClass<any> = jest.fn((...args) => {
        const instance = Object.create(mockClass.prototype);

        return Object.assign(instance, { args });
    })

    return {
        MyClass: mockClass
    }
});

字符串

yvt65v4c

yvt65v4c3#

instanceof操作符测试构造函数的prototype属性是否出现在对象的prototype链中的任何位置。
这意味着您可以将mock的原型更改为A

yh2wf1be

yh2wf1be4#

如果mocked类的复杂实现无关紧要(在单元测试阶段不应该这样),那么你可以使用ts-ignore。这将允许TypeScript编译器重写实现,而不必担心mocking复杂依赖。
这就是我如何做到这一点,它为我的aws-cdk应用程序之一的目的。
主代码

Aspects.of(this.cdkStack).add(new MyGlobalDenyAspect());

字符串
嘲笑

const mockCdkStackImpl = { class: 'aws-cdk-lib/Stack', isMocked: true };
const mockAdd = jest.fn();
/*Notice Aspects.of returns an instance of the Aspects, but the 
following code replaces it to return a custom function that matches the 
expected implementation*/
const aspectsOfMock = jest
  .spyOn(Aspects, 'of')
  // @ts-ignore
  .mockImplementation(() => ({ add: mockAdd }));


测试

it('should call aws cdk Aspects.of with cdk stack', () => {
expect(aspectsOfMock).toHaveBeenCalled(mockCdkStackImpl);
});

it('should call aws cdk Aspects.add with LmGlobalDenyAspect type', () 
=> {        
expect(mockAdd).toHaveBeenCalledWith(expect.any(MyGlobalDenyAspect));
});

相关问题