Cách thay đổi việc triển khai mô hình trên một cơ sở thử nghiệm duy nhất [Jestjs]


88

Tôi muốn thay đổi việc triển khai phụ thuộc được chế tạo trên một cơ sở thử nghiệm đơn lẻ bằng cách mở rộng hành vi của mô hình mặc địnhhoàn nguyên nó về triển khai ban đầu khi thử nghiệm tiếp theo thực hiện.

Nói ngắn gọn hơn, đây là những gì tôi đang cố gắng đạt được:

  1. sự phụ thuộc giả
  2. thay đổi / mở rộng triển khai mô hình trong một thử nghiệm duy nhất
  3. hoàn nguyên về mô hình ban đầu khi thử nghiệm tiếp theo thực hiện

Tôi hiện đang sử dụng Jest v21 .

Đây là một bài kiểm tra Jest điển hình sẽ trông như thế nào:

__mocks__/myModule.js

const myMockedModule = jest.genMockFromModule('../myModule');

myMockedModule.a = jest.fn(() => true);
myMockedModule.b = jest.fn(() => true);

export default myMockedModule;

__tests__/myTest.js

import myMockedModule from '../myModule';

// Mock myModule
jest.mock('../myModule');

beforeEach(() => {
  jest.clearAllMocks();
});

describe('MyTest', () => {
  it('should test with default mock', () => {
    myMockedModule.a(); // === true
    myMockedModule.b(); // === true
  });

  it('should override myMockedModule.b mock result (and leave the other methods untouched)', () => {
    // Extend change mock
    myMockedModule.a(); // === true
    myMockedModule.b(); // === 'overridden'
    // Restore mock to original implementation with no side effects
  });

  it('should revert back to default myMockedModule mock', () => {
    myMockedModule.a(); // === true
    myMockedModule.b(); // === true
  });
});

Đây là những gì tôi đã thử cho đến nay:


1 - mockFn.mockImplementationOnce (fn)

thuận

  • Hoàn nguyên về triển khai ban đầu sau cuộc gọi đầu tiên

khuyết điểm

  • Nó bị hỏng nếu thử nghiệm gọi bnhiều lần
  • Nó không hoàn nguyên về triển khai ban đầu cho đến khi bkhông được gọi (rò rỉ trong thử nghiệm tiếp theo)

mã:

it('should override myModule.b mock result (and leave the other methods untouched)', () => {

  myMockedModule.b.mockImplementationOnce(() => 'overridden');

  myModule.a(); // === true
  myModule.b(); // === 'overridden'
});

2 - jest.doMock (moduleName, factory, options)

thuận

  • Chế nhạo lại rõ ràng mọi bài kiểm tra

khuyết điểm

  • Không thể xác định triển khai mô hình mặc định cho tất cả các thử nghiệm
  • Không thể mở rộng triển khai mặc định buộc phải khai báo lại từng phương thức bị chế nhạo

mã:

it('should override myModule.b mock result (and leave the other methods untouched)', () => {

  jest.doMock('../myModule', () => {
    return {
      a: jest.fn(() => true,
      b: jest.fn(() => 'overridden',
    }
  });

  myModule.a(); // === true
  myModule.b(); // === 'overridden'
});

3 - Mô phỏng thủ công với các phương pháp setter (như được giải thích ở đây )

thuận

  • Toàn quyền kiểm soát các kết quả bị chế nhạo

khuyết điểm

  • Rất nhiều mã lò hơi
  • Khó duy trì lâu dài

mã:

__mocks__/myModule.js

const myMockedModule = jest.genMockFromModule('../myModule');

let a = true;
let b = true;

myMockedModule.a = jest.fn(() => a);
myMockedModule.b = jest.fn(() => b);

myMockedModule.__setA = (value) => { a = value };
myMockedModule.__setB = (value) => { b = value };
myMockedModule.__reset = () => {
  a = true;
  b = true;
};
export default myMockedModule;

__tests__/myTest.js

it('should override myModule.b mock result (and leave the other methods untouched)', () => {
  myModule.__setB('overridden');

  myModule.a(); // === true
  myModule.b(); // === 'overridden'

  myModule.__reset();
});

4 - jest.spyOn (object, methodName)

khuyết điểm

  • Tôi không thể hoàn nguyên trở mockImplementationlại giá trị trả về bị chế nhạo ban đầu, do đó sẽ ảnh hưởng đến các thử nghiệm tiếp theo

mã:

beforeEach(() => {
  jest.clearAllMocks();
  jest.restoreAllMocks();
});

// Mock myModule
jest.mock('../myModule');

it('should override myModule.b mock result (and leave the other methods untouched)', () => {

  const spy = jest.spyOn(myMockedModule, 'b').mockImplementation(() => 'overridden');

  myMockedModule.a(); // === true
  myMockedModule.b(); // === 'overridden'

  // How to get back to original mocked value?
});

Đẹp. Nhưng làm thế nào để bạn thực hiện tùy chọn 2 cho một mô-đun npm như '@ private-repo / module'? Hầu hết các ví dụ tôi thấy có đường dẫn tương đối? Điều này cũng hoạt động cho các mô-đun đã cài đặt?
mrbinky3000

Câu trả lời:


47

Một mô hình hay cho kiểm tra viết là tạo một chức năng cài đặt gốc trả về dữ liệu bạn cần để kiểm tra mô-đun hiện tại.

Dưới đây là một số mã mẫu sau ví dụ thứ hai của bạn mặc dù cho phép cung cấp các giá trị mặc định và ghi đè theo cách có thể sử dụng lại.

const spyReturns = returnValue => jest.fn(() => returnValue);

describe("scenario", () => {
  const setup = (mockOverrides) => {
    const mockedFunctions =  {
      a: spyReturns(true),
      b: spyReturns(true),
      ...mockOverrides
    }
    return {
      mockedModule: jest.doMock('../myModule', () => mockedFunctions)
    }
  }

  it("should return true for module a", () => {
    const { mockedModule } = setup();
    expect(mockedModule.a()).toEqual(true)
  });

  it("should return override for module a", () => {
    const EXPECTED_VALUE = "override"
    const { mockedModule } = setup({ a: spyReturns(EXPECTED_VALUE)});
    expect(mockedModule.a()).toEqual(EXPECTED_VALUE)
  });
});

41

Vanilla JS

Sử dụng mockFn.mockImplementation (fn) .

import { funcToMock } from './somewhere';
jest.mock('./somewhere');

beforeEach(() => {
  funcToMock.mockImplementation(() => { /* default implementation */ });
});

test('case that needs a different implementation of funcToMock', () => {
  funcToMock.mockImplementation(() => { /* implementation specific to this test */ });
  // ...
});

TypeScript

Để ngăn thông báo mockImplementation không phải là một thuộc tính của funcToMock , bạn sẽ cần chỉ định loại, ví dụ: bằng cách thay đổi dòng trên cùng từ phía trên thành dòng sau:

import { (funcToMock as jest.Mock) } from './somewhere';

Một câu hỏi giải quyết vấn đề này có thể được tìm thấy ở đây: mô hình thuộc tính jest stylescript không tồn tại trên loại


21

Đến bữa tiệc hơi muộn, nhưng nếu ai đó đang gặp vấn đề với điều này.

Chúng tôi sử dụng TypeScript, ES6 và babel để phát triển phản ứng gốc.

Chúng tôi thường mô phỏng các mô-đun NPM bên ngoài trong thư mục gốc __mocks__ thư mục .

Tôi muốn ghi đè một chức năng cụ thể của một mô-đun trong lớp Auth của aws-amplify cho một bài kiểm tra cụ thể.

    import { Auth } from 'aws-amplify';
    import GetJwtToken from './GetJwtToken';
    ...
    it('When idToken should return "123"', async () => {
      const spy = jest.spyOn(Auth, 'currentSession').mockImplementation(() => ({
        getIdToken: () => ({
          getJwtToken: () => '123',
        }),
      }));

      const result = await GetJwtToken();
      expect(result).toBe('123');
      spy.mockRestore();
    });

Gist: https://gist.github.com/thomashagstrom/e5bffe6c3e3acec592201b6892226af2

Hướng dẫn: https://medium.com/p/b4ac52a005d#19c5

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.