Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vitest spyOn has different behaviour than jest's #1329

Closed
6 tasks done
galkatz373 opened this issue May 17, 2022 · 6 comments
Closed
6 tasks done

Vitest spyOn has different behaviour than jest's #1329

galkatz373 opened this issue May 17, 2022 · 6 comments

Comments

@galkatz373
Copy link

Describe the bug

Hey!
It seems the vitest spyOn doesn't have the same behaviour as the jest's (see reproduction)

Reproduction

vitest project reproduction: https://stackblitz.com/edit/vitest-dev-vitest-ne8pti?file=src%2Fexample.ts,test%2Fbasic.test.ts,package.json&initialPath=__vitest__

jest project reproduction: https://github.com/galkatz373/jest-example

System Info

macOS 12.0.1, node 16.6.0

Used Package Manager

npm

Validations

@sheremet-va
Copy link
Member

sheremet-va commented May 18, 2022

This is not about spyOn, but about how babel transforms typescript files.

Vite transforms files to something like this:

const func = () => {}
const combine = () => {
  func()
}
Object.definePropertry(__vite_exports__, 'func', {
  get: () => func
})
Object.definePropertry(__vite_exports__, 'combine', {
  get: () => combine
})

spyOn just spies on a call to __vite_exports__.func, but since func was called as a standalone function, we cannot spy on it.

I assume, babel saves pointers to functions somehow.

This is out of scope of Vitest. Maybe you can point to Vite repo for the solution. I will not close this issue for now, in case you have any questions.

@galkatz373
Copy link
Author

Thanks for the quick response! what would you say the workaround? besides potentially changing vite itself

@sheremet-va
Copy link
Member

If you store methods on an object or class, you can spy on them without problem:

// funcs.ts
class Helper {
  func() {}
  
  combine() {
    this.func()
  }
}

export const helper = new Helper()

// or

export const helper = {
  func: () => {},
  combine: () => {
    helper.func()
  }
}

// test.ts
import { helper } from './funcs'

vi.spyOn(helper, 'func').mockReturnOnce(100)

@gugadev
Copy link

gugadev commented Oct 7, 2022

@sheremet-va works as well without instances but class level? For example, Helper class is injected by DI inside a Component and I want to test the component by mocking the class methods. Does Vitest support something like vi.spyOn(Helper.prototype, "func").mockReturnOnce(100)? Thanks.

@sheremet-va
Copy link
Member

@sheremet-va works as well without instances but class level? For example, Helper class is injected by DI inside a Component and I want to test the component by mocking the class methods. Does Vitest support something like vi.spyOn(Helper.prototype, "func").mockReturnOnce(100)? Thanks.

Yes, it works.

@unicornware
Copy link

unicornware commented Mar 11, 2023

@sheremet-va works as well without instances but class level? For example, Helper class is injected by DI inside a Component and I want to test the component by mocking the class methods. Does Vitest support something like vi.spyOn(Helper.prototype, "func").mockReturnOnce(100)? Thanks.

Yes, it works.

@sheremet-va

are there any docs or examples regarding class level spies? i've scoured the docs site, but didn't see any references. not sure if i'm just overlooking them, however.

i'm finding that call counts are not recorded with a class level spy. my goal is to ensure the method updateRepository has been called once (toHaveBeenCalledOnce). i've tried the following patterns:

  • vi.spyOn(Manager.prototype, 'updateRepository')
  • vi.spyOn(Manager.default.prototype, 'updateRepository') (the Manager class is default exported)
  • mocking Manager, then using vi.mock('#src/models/manager') instead of vi.spyOn

none of the patterns above got my test working. any thoughts? (no bug btw, i'm just doing something wrong and looking for a working example haha 😅)

@github-actions github-actions bot locked and limited conversation to collaborators Jun 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants