bun icon indicating copy to clipboard operation
bun copied to clipboard

`mock` and `spyOn` are not reset after each test

Open joshivaibhavs opened this issue 9 months ago • 7 comments

What version of Bun is running?

1.0.3+25e69c71e70ac8a0a88f9cf15b4057bd7b2a633a

What platform is your computer?

Linux 5.15.0-83-generic x86_64 x86_64

What steps can reproduce the bug?

  1. Create a file MyModule.ts
  2. Export a class MyClass from the module with following structure:
export class MyClass {
    myMethod() {
        return 'Hello';
    }
}
  1. Create a file MyModule.test.ts
  2. Write a test that tests the myMethod
test('myMethod return value', () => {
    const value = new MyClass().myMethod();
    expect(value).toEqual('Hello');
})
  1. Create another file OtherModule.test.ts
  2. Mock / spyOn the myMethod.
spyOn(MyClass.prototype, 'myMethod').mockImplementation(() => 'Hola');
  1. The myMethod return value test starts failing like this:
error: expect(received).toEqual(expected)

Expected: "Hello"
Received: "Hola"

What is the expected behavior?

The mocks / spyOns should be contained within individual test suites.

What do you see instead?

The mock is being applied across the test suites. All implementations are now mocked. Also, mockRestore doesn't seem to work.

Additional information

No response

joshivaibhavs avatar Sep 25 '23 14:09 joshivaibhavs

I have the same problem, tests are flaky, if I mock a module in a test suit, then I can't test the module itself in another test suit. Tests are passing well in isolation but not together.

aralroca avatar Jan 20 '24 08:01 aralroca

Yeah same issue here, no ability to manually clear them as far as I can tell too?

dec-land avatar Jan 21 '24 02:01 dec-land

I am also experiencing this issue, if anyone has a workaround that would be great

chlorophant avatar Jan 22 '24 05:01 chlorophant

This snippet should restore all mocks, including modules and spyOn values:

import {jest} from 'bun:test';

jest.restoreAllMocks();

It's a little unclear what to do about this to make it automatic.

Complete test isolation is a big performance hit without a lot of time spent investigating different implementations

A simple thing we could do: automatically clear all mocked modules, calls, return values etc at the end of each test file. This would mean if you want persistently-mocked modules they'd have to go in --preload (which might be fine).

But it would mean if you imported a file which loads some test helpers outside of --preload, it wouldn't reload that test helper. Mocks from test helpers loaded outside of --preload mock would be applied for one test file, and then never reloaded again.

Jarred-Sumner avatar Jan 22 '24 05:01 Jarred-Sumner

Is jest.restoreAllMocks() supposed to work with mock.module?

It didn't work for my case.

I'm having an issue where two test files are mocking the same module, and causing conflicts for eachother. If I just run the testsfiles individually they work fine. ATM the only solution for me was to not test some functionality, but its not ideal.

I thought maybe it was related to the import path, as I am using import aliases, but I changed it all to relative imports and it didnt help.

Hoping to get this sorted, as its the last piece I need for my org to buyoff on using this for production.

Also, btw, @Jarred-Sumner Thanks for all the hard work, I'm loving bun!

chlorophant avatar Jan 22 '24 06:01 chlorophant

I am also experiencing this issue, if anyone has a workaround that would be great

@chlorophant As a workaround instead of importing directly from the module, I have created another file to import it from there so that when testing the mock it does not affect the tests with the module. Very tricky because I had to adapt the code to pass the tests, but as a workaround it worked for me, although I hope it will be solved soon.

aralroca avatar Jan 22 '24 13:01 aralroca

Yeah thats unfortunate as it seems you would need a wrapper file for each time you need to mock it. Thanks for the idea though, that may unblock me.

UPDATE: I just created a deps file next to every source file and that has all deps imported and re-exported. Then my file can import and my test can mock, and everyone is happy. Seems to be working well.

Thanks for the suggestion. It does add a lot of file bloat but at least it works!

chlorophant avatar Jan 22 '24 16:01 chlorophant

It's a little unclear what to do about this to make it automatic.

@Jarred-Sumner Just a suggestion: as @mattpocock commented on Twitter the new 'using' keyword is awesome for mocking in tests. It automatically disposes the 'mock' when it leaves scope

aralroca avatar Jan 27 '24 17:01 aralroca