简体   繁体   中英

How to mock uuid with Jest

so on my search for an answer to my problem I found this post: Jest: How to globally mock node-uuid (or any other imported module)

I already tried the answer but I can't seem to use it properly, as it´s giving me an undefined error. I'm new to the testing scene so please excuse any major errors:

This was my first approach

const mockF = jest.mock('uuid'); 

mockF.mockReturnValue('12345789'); 

But it wouldn't recognize the functions.

"mockF.mockReturnValue is not a function" among others I tried.

Then I tried to manually mock as the post suggested but can' seem to make it work, can you help me? Thanks

Here's the entire test if it helps:

    const faker = require('faker');
    const storageUtils = require('../../storage/utils');
    const utils = require('../utils/generateFile');
    const { generateFileName } = storageUtils;
    const { file } = utils;

    test('should return a valid file name when provided the correct information', () => {
        // ARRANGE
        // create a scope
        const scope = {
            type: 'RECRUITER',
            _id: '987654321',
        };
        // establish what the expected name to be returned is
        const expectedName = 'r_987654321_123456789.png';

        jest.mock('uuid/v4', () => () => '123456789');

        // ACTION
        const received = generateFileName(file, scope);

        // ASSERT
        // expect the returned value to equal our expected one
        expect(received).toBe(expectedName);
    });

I figure I might as well add my solution here, for posterity. None of the above was exactly what I needed:

jest.mock('uuid', () => ({ v4: () => '123456789' }));

By the way, using a variable instead of '123456789' breaks it.

This should be mocked where we have the imports and it does not require you to explicitely import uuid in your spec file.

Mock it by using mockImplementation .

import uuid from 'uuid/v4';
jest.mock('uuid/v4');

describe('mock uuid', () => {
  it('should return testid }', () => {
    uuid.mockImplementation(() => 'testid');
    ...
  });  
});

Make sure you import uuid correctly (with correct version reference eg v4, v3...)

Assuming the following test file, you can use the jest.spyOn call to mock out uuid.

Test.spec.js

import uuid from 'uuid';
import testTarget from './testTarget';

describe('mock uuid', () => {
  it('should return testid }', () => {
    // Arrange
    const anonymousId = 'testid';
    const v1Spy = jest.spyOn(uuid, 'v1').mockReturnValue(anonymousId);

    // Act
    const result = testTarget();

    // Assert
    expect(result).toEqual(anonymousId);
    expect(v1Spy).toHaveBeenCalledTimes(1);
  });  
});

testTarget.js

import uuid from 'uuid';
export default function() {
   return uuid.v1();
}

This worked for me. In my case I only wanted to verify that the function was called rather than asserting on a specific value.

import * as uuid from 'uuid';
jest.mock('uuid');

const uuidSpy = jest.spyOn(uuid, 'v4');

// in a test block
expect(uuidSpy).toHaveBeenCalledTimes(1);

for my case I used the answer of this Github issue

jest.mock('uuid/v4', () => {
 let value = 0;
 return () => value++;
});

Hopefully the following two examples will be helpful.

Say you need a JS module whose sole resposibility is to generate UUIDs. Taking a TDD approach we start with an assertion and eventually see we need some UUIDGenerator with some method to return UUIDs:

it('should generate UUID', () => {
    const myUUID = UUIDGenerator.nextUUID();
    expect(myUUID).toEqual('some-short-v4-uuid-0');
});

The test, shapes UUIDGenerator.ts into the following code:

import {v4 as uuidv4} from 'uuid';
const UUIDGenerator = {
  storeUUID(): string {
    return uuidv4();
  }
};
export default UUIDGenerator;

Now we want to mock UUIDGenerator 's dependency on the uuid module. We can do this by Calling jest.mock() with the module factory parameter as documented on jestjs.io . We can now simply describe how jest should behave,

jest.mock('uuid',() => ({
    v4: () => 'some-short-v4-uuid-0'
}));
describe('UUIDGenerator', () => { 
    // it block from above
});

You should now see you test passing.

The other alternative is to create some uuid.ts somewhere in your project:

import {v4 as uuidv4} from 'uuid';
export default uuidv4;

and import it in UUIDGenerator.ts :

import uuidv4 from '../uuid';

in this case, you should be able to mock your uuid.ts . I placed mine in the parent directory (relative to UUIDGenerator.ts ) so you can see an example on how to find it when not in the same directory.

jest.mock('../uuid',
  () => jest.fn(() => '1-234-5678')
);

This works for me

import { v1 as uuidv1 } from 'uuid';

jest.mock('uuid');


... # (somewhere on your test suite)

uuidv1.mockImplementationOnce(() => {
  return 'uuid-123';
});
import uuid from 'uuid'

describe('some test', () => {
  it('some test 1', () => {
     const uuidMock = jest.spyOn(uuid, 'v4').mockReturnValue('123434-test-id-dummy');

     // expect(uuidMock).toHaveBeenCalledTimes(<number of times called>);

  })
})

As per this answer: How do I write test case for a function which uses uuid using jest?

You can use jest.mock inorder to mock the import of uuid, like that:

const uuidMock = jest.fn().mockImplementation(() => {
    return 'my-none-unique-uuid';
});
jest.mock('uuid', () => {
    return uuidMock;
});

The only caveat of that approach is that you need to apply the mock in the test file before you are importing your real file .

Then you will even able to assert on the mock.

this worked for me (I'm using typescript, you can remove the as blablabla if you aren't):

jest.mock('uuid', () => ({
  v4: jest.fn(),
}));
const mockUuid = require('uuid') as { v4: jest.Mock<string, []> };

beforeEach(() => {
  mockUuid.v4.mockImplementationOnce(
    () => 'your-mocked-id',
  );
});

https://github.com/facebook/jest/issues/2172#issuecomment-756921887

You can have problems if you put jest.mock('uuid') in wrong scope.

This is correct for me:

import * as uuid from 'uuid';
jest.mock('uuid');
describe('utils', () => {
    it('test', () => {
        jest.spyOn(uuid, 'v4').mockReturnValue('mockedValue')
    });
});

and this is incorrect :

import * as uuid from 'uuid';
describe('utils', () => {
    it('test', () => {
        jest.mock('uuid');
        jest.spyOn(uuid, 'v4').mockReturnValue('mockedValue')
    });
});

I had the same issue/challenge today. In the end my solution looks like this.

Code (usage):

import { v4 as uuidv4 } from 'uuid';
...
const uuid = uuidv4();
...

Test:

jest.mock('uuid', () => ({ v4: () => 'adfd01fb-309b-4e1c-9117-44d003f5d7fc' }));
...
describe('Test Foo', () => {
  ...
});

IMPORTANT: You need to mock it before the first "describe" block.

I am using typescript and this worked for me.

jest.mock('uuid', () => {
  return {
    __esModule: true,
    v4: jest.fn().mockReturnValue('9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'),
  };
});

describe("Test suit", () => {
// your tests
});

This actually works

jest.mock('uuid', () => {
  const originalModule = jest.requireActual('uuid');
  return {
    __esModule: true,
    ...originalModule,
    v4: jest.fn(() => '634b59eb-dc11-48f0-ad46-ca2d85ef2a9d')
  };
});

However, you have to define this on top of your testing file. Not in beforeAll() .

See mock functions in jest for more information.

Nothing above worked until I brute forced it for using uuid npm package's v4 method:

import { v4 } from 'uuid'

jest.mock('uuid', () => ({
    v4: jest.fn(),
}))

beforeEach(() => {
  ;(v4 as jest.Mock).mockReturnValue('mock-uuid-1234')
}

afterEach(() => {
  jest.clearAllMocks()
}

Hope this helps.

Other answers will solve the issue for you, but I prefer to set the mocked value to a variable so you aren't copy/pasting a hard-coded string all over your tests.

const mockUUID = 'mocked-uuid'
jest.mock('uuid', () => ({ v4: () => mockUUID }))

The important thing to note is that you must start the variable name with mock for it to work properly. More info can be found here: https://jestjs.io/docs/es6-class-mocks#calling-jestmock-with-the-module-factory-parameter

It's really well explained in the documentation , but in general you can:

const mockF = jest.fn().mockReturnValue('12345789');

or

import uuid from 'uuid';
jest.mock('uuid', () => 
    jest.fn().mockReturnValue('12345789');
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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