用模块模式开玩笑地模拟模块并在每个测试中具有独特的功能

Jest mocking a module with module pattern and having unique functionality on each test

我无法通过我拥有的模块模式设置(MyConnection.js)进行搜索的独特实现 - 这与我拥有的类似:

// MyConnection.js
const MyConnection = () => {
  const search = async (q) => {
    //...some functionality
  };
  return {
    search,
  };
};
  

//JEST TESTS
const MyConnection = require('../MyConnection')

// this works - but it sets the search implementation 
// for the whole test file I believe
jest.mock('../MyConnection', () => {
    return jest.fn(()=>{
        search: ()=> ['mocked', 'fn', 'results']
    })
})


//the jest tests - I want different 
// implementations of search in each test
describe('connection tests', ()=>{

    it('test one', ()=>{

        //Not sure if its something like this to set 'search' for each test? This doesn't work as is
        MyConnection.search.mockImplementation((q)=>{`You searched ${q}`})
    })

    it('test two', ()=>{
        MyConnection.search.mockImplementation((q)={q.length>32? 'a': 'b' }})
    })

})

如何为每个测试获取该搜索功能的独特 Jest 模拟实现?

您应该确保 mock MyConnection 始终return在您的测试文件和您要测试的模块中使用相同的连接对象。

MyConnection.js:

const MyConnection = () => {
  const search = async (q) => {};
  return {
    search,
  };
};

module.exports = MyConnection;

main.js:

const MyConnection = require('./MyConnection');

async function main(q) {
  const conn = MyConnection();
  return conn.search(q);
}

module.exports = main;

main.test.js:

const MyConnection = require('./MyConnection');
const main = require('./main');

jest.mock('./MyConnection', () => {
  console.log('MyConnection module gets mocked');
  const conn = { search: jest.fn() };
  return jest.fn(() => conn);
});
const mConn = MyConnection();

describe('connection tests', () => {
  it('test one', async () => {
    mConn.search.mockImplementation((q) => {
      return `You searched ${q}`;
    });
    const actual = await main('teresa teng');
    expect(actual).toBe('You searched teresa teng');
  });

  it('test two', async () => {
    mConn.search.mockImplementation((q) => {
      return q.length > 32 ? 'a' : 'b';
    });
    const actual = await main('_');
    expect(actual).toBe('b');
  });
});

测试结果:

 PASS  examples/70132655/main.test.js (10.454 s)
  connection tests
    ✓ test one (2 ms)
    ✓ test two (1 ms)

  console.log
    MyConnection module gets mocked

      at examples/70132655/main.test.js:5:11

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        10.903 s

不能这样嘲笑它:

jest.mock('./MyConnection', () => {
  console.log('MyConnection module gets mocked');
  return jest.fn(() => { search: jest.fn() });
});

为什么?因为每次在测试文件或者你要测试的文件中调用MyConnection()函数。它将return一个新的模拟对象({ search: jest.fn() }),被测文件中的模拟对象和测试用例不一样。