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

Time:12-01

I'm having trouble having a unique implementation of search from this module pattern setup I have (MyConnection.js) - here's similar to what I have:

// 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' }})
    })

})

How can I get unique Jest mock implementations of that search function for each test?

CodePudding user response:

You should make sure that mock MyConnection always returns the same connection object in your test file and the module you want to test.

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');
  });
});

test result:

 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

You can't mock it like this:

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

Why? Because every time you call the MyConnection() function in the test file or the file you want to test. It will return a new mock object({ search: jest.fn() }), the mock objects in file under test and test case are not same.

  • Related