39

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);
    });
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Eduardo Pinto
  • 493
  • 1
  • 4
  • 8

17 Answers17

30

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.

Saksham
  • 9,037
  • 7
  • 45
  • 73
Mason Embry
  • 546
  • 6
  • 4
  • 2
    You should improve your answer by specifying the imports and the scope where it is declared – Saksham Apr 21 '22 at 11:48
  • 3
    This. I spent almost two hours trying to figure it out, I had tried the same exact syntax (with nanoid though) and kept failing. The trick is to place it right after the imports and avoid using variables... – Fi Li Ppo Aug 17 '22 at 13:01
  • This solution worked for me, where the others didn't. There is no import statement needed. I was able to define this inside a `beforeAll` function. – sfuqua Dec 15 '22 at 19:24
22

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 e.g. v4, v3...)

squaleLis
  • 6,116
  • 2
  • 22
  • 30
Shadrech
  • 453
  • 4
  • 11
  • 6
    I did as it is provided in the example and got this error: Property 'mockImplementation' does not exist on type 'v4'. – EA0906 Sep 04 '19 at 08:37
  • @EA0906 is it TS error? if so, I've found a solution here: https://klzns.github.io/how-to-use-type-script-and-jest-mocks – Alexander Kleshchukevich Jan 20 '20 at 11:19
  • Google is not cooperating when I search for jasmine tests, for those who also land here: `import * as uuid from 'uuid';` and in your test: `spyOn(uuid, 'v4').and.returnValue('test-id');` – CularBytes Oct 21 '20 at 13:51
  • 1
    @EA0906 You need to use `const uuidVX = require('uuid/vX')` instead of `import` for your particular issue. Then you can call `mockImplementation` on it. – taystack Dec 15 '20 at 21:23
15

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);
adam.shaleen
  • 993
  • 3
  • 9
  • 20
  • Thanks. This method also works fine for me when using `mockReturnValue` too: `import * as uuid from "uuid"; jest.mock("uuid"); describe("someTest", () => { const uuidSpy = jest.spyOn(uuid, "v4"); uuidSpy.mockReturnValue("some-uuid");` – james246 Nov 03 '21 at 15:07
11

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')
    });
});
Tomek Tajne
  • 658
  • 7
  • 7
10

for my case I used the answer of this Github issue

jest.mock('uuid/v4', () => {
 let value = 0;
 return () => value++;
});
JAM
  • 6,045
  • 1
  • 32
  • 48
Henrique Jensen
  • 399
  • 3
  • 6
9

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();
}
seetdev
  • 577
  • 1
  • 5
  • 11
5

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')
);
raulra08
  • 191
  • 2
  • 5
  • One of the other approaches above worked for me... for one test, but then it was problematic when I needed it in another test. I ended up converging on a similar solution as this one (wrapper object), and in the end I think it is a better solution. – sfuqua Dec 15 '22 at 19:48
4

This works for me

import { v1 as uuidv1 } from 'uuid';

jest.mock('uuid');


... # (somewhere on your test suite)

uuidv1.mockImplementationOnce(() => {
  return 'uuid-123';
});
Dharman
  • 30,962
  • 25
  • 85
  • 135
Pevin
  • 61
  • 2
  • Yes, indeed. Placing the mock before the describe statement works. Thank you! `jest.mock('uuid', () => ({ v4: () => 'xxx' }));` – Michael Pacheco Feb 17 '22 at 00:48
4

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.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Barry Norman
  • 174
  • 7
2

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.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
IYves
  • 21
  • 2
  • See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 11 '22 at 04:01
  • This is the best solution for packages that export a uuid function. Jest's actual [requireActual example](https://jestjs.io/docs/jest-object#jestrequireactualmodulename) is this very same use case: mocking a getRandom function. – Matthias Mar 17 '23 at 23:38
  • As an improvement, jest will allow the implementation to reference a `mockNextUuid` variable, but **only** if the variable name starts with "mock" (as per the error message). – Matthias Mar 17 '23 at 23:40
1

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

  • See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 11 '22 at 04:02
1

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
});
  • See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 11 '22 at 04:02
1

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

c0d3ster
  • 51
  • 3
0
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>);

  })
})
dakshgautam
  • 39
  • 1
  • 6
  • 2
    While this code may answer the question, it would be better to explain how it solves the problem without introducing others and why to use it. Code-only answers are not useful in the long run. – Al Foиce ѫ Sep 12 '19 at 20:12
0

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.

Reid
  • 4,376
  • 11
  • 43
  • 75
0

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.

Taiwei Tuan
  • 430
  • 2
  • 12
-1

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');
);
Teneff
  • 30,564
  • 13
  • 72
  • 103