简体   繁体   English

Mocking 向上 static 方法开玩笑

[英]Mocking up static methods in jest

I am having trouble mocking up a static method in jest.我在开玩笑的 static 方法上遇到了麻烦 mocking。 Immagine you have a class A with a static method:想象一下你有一个 class A 和一个 static 方法:

export default class A {
  f() {
    return 'a.f()'
  }

  static staticF () {
    return 'A.staticF()'
  }
}

And a class B that imports A和一个进口A的class B

import A from './a'

export default class B {
  g() {
    const a = new A()
    return a.f()  
  }

  gCallsStaticF() {
    return A.staticF()
  }
}

Now you want to mock up A. It is easy to mock up f():现在你想模拟 A。模拟 f() 很容易:

import A from '../src/a'
import B from '../src/b'

jest.mock('../src/a', () => {
  return jest.fn().mockImplementation(() => {
    return { f: () => { return 'mockedA.f()'} }
  })
})

describe('Wallet', () => {
  it('should work', () => {
    const b = new B()
    const result = b.g()
    console.log(result) // prints 'mockedA.f()'
  })
})

However, I could not find any documentation on how to mock up A.staticF.但是,我找不到任何关于如何模拟 A.staticF 的文档。 Is this possible?这可能吗?

You can just assign the mock to the static method您可以将模拟分配给静态方法

import A from '../src/a'
import B from '../src/b'

jest.mock('../src/a')

describe('Wallet', () => {
    it('should work', () => {
        const mockStaticF = jest.fn().mockReturnValue('worked')

        A.staticF = mockStaticF

        const b = new B()

        const result = b.gCallsStaticF()
        expect(result).toEqual('worked')
    })
})

Hope this will help you希望对你有帮助

// code to mock
export class AnalyticsUtil {
    static trackEvent(name) {
        console.log(name)
    }
}

// mock
jest.mock('../src/AnalyticsUtil', () => ({
    AnalyticsUtil: {
        trackEvent: jest.fn()
    }
}))
// code to mock
export default class Manager {
    private static obj: Manager
    
    static shared() {
        if (Manager.obj == null) {
            Manager.obj = new Manager()
        }
        return Manager.obj
    }
    
    nonStaticFunc() {
    }
}

// mock
jest.mock('../src/Manager', () => ({
    shared: jest.fn().mockReturnValue({
        nonStaticFunc: jest.fn()
    })
}))
// usage in code
someFunc() {
    RNDefaultPreference.set('key', 'value')
}

// mock RNDefaultPreference
jest.mock('react-native-default-preference', () => ({
    set: jest.fn()
}))
// code to mock
export namespace NavigationActions {
    export function navigate(
      options: NavigationNavigateActionPayload
    ): NavigationNavigateAction;
}

// mock
jest.mock('react-navigation', () => ({
    NavigationActions: {
        navigate: jest.fn()
    }
}))

I managed to mock it in a separate file in the __mocks__ folder using prototyping.我设法使用原型在__mocks__文件夹中的一个单独文件中模拟它。 So you would do:所以你会这样做:

function A() {}
A.prototype.f = function() {
    return 'a.f()';
};
A.staticF = function() {
    return 'A.staticF()';
};
export default A;

We need to create a mock and give visibility for the mocked method to the test suite.我们需要创建一个模拟并将模拟方法的可见性提供给测试套件。 Below full solution with comments.以下带有评论的完整解决方案。

let mockF; // here we make variable in the scope we have tests
jest.mock('path/to/StaticClass', () => {
  mockF = jest.fn(() => Promise.resolve()); // here we assign it
  return {staticMethodWeWantToMock: mockF}; // here we use it in our mocked class
});

// test
describe('Test description', () => {
  it('here our class will work', () => {
    ourTestedFunctionWhichUsesThisMethod();
    expect(mockF).toHaveBeenCalled(); // here we should be ok
  })
})

Jest Spies笑话间谍

I went with the route of using jest.spyOn .我选择了使用jest.spyOn的路线。

Example例子

encryption.ts

export class Encryption {
  static encrypt(str: string): string {
     // ...
  }

  static decrypt(str: string): string {
    // ...
  }
}

property-encryption.spec.ts

import { Encryption } from './encryption'
import { PropertyEncryption } from './property-encryption'

describe('PropertyEncryption', () => {
  beforeAll(() => {
    jest
      .spyOn(Encryption, 'encrypt')
      .mockImplementation(() => 'SECRET')
    jest
      .spyOn(Encryption, 'decrypt')
      .mockImplementation(() => 'No longer a secret')
  })

  it("encrypts object values and retains the keys", () => {
    const encrypted = PropertyEncryption.encrypt({ hello: 'world' });

    expect(encrypted).toEqual({ hello: 'SECRET' });
  });

  it("decrypts object values", () => {
    const decrypted = PropertyEncryption.decrypt({ hello: "SECRET" });

    expect(decrypted).toEqual({ hello: 'No longer a secret' });
  });
})

Using Object.assign on the mock constructor allows simultaneous mocking of the class and its static methods.在模拟构造函数上使用Object.assign允许同时模拟类及其静态方法。 Doing this allows you to achieve the same structure you get when creating a class with static members.这样做可以让您获得与创建具有静态成员的类时相同的结构。

    import A from '../src/a'
    import B from '../src/b'


    jest.mock('../src/a', () =>
      Object.assign(
        jest.fn(
          // constructor
          () => ({
            // mock instance here
            f: jest.fn()
          })),
        { 
         // mock static here
          staticF: jest.fn(),
        }
      )
    )

Here's an example with an ES6 import.这是一个 ES6 导入的示例。

import { MyClass } from '../utils/my-class';
const myMethodSpy = jest.spyOn(MyClass, 'foo');

describe('Example', () => {
    it('should work', () => {
        MyClass.foo();
        expect(myMethodSpy).toHaveBeenCalled();
    });
 });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM