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

verifyAllMocksCalled functionality #12

Closed
buck06191 opened this issue May 10, 2024 · 3 comments
Closed

verifyAllMocksCalled functionality #12

buck06191 opened this issue May 10, 2024 · 3 comments

Comments

@buck06191
Copy link

What

In jest-when there's a feature we use at our company that verifies all of the when mocks are called by the end of a test -https://github.com/timkindberg/jest-when/blob/master/src/when.js#L216

In order for us to migrate to vitest it would be really good to have this added in to vitest-when.

Do you think this is something you'd consider adding in? We could look at raising a PR ourselves as a proposal if that's the case

@mcous
Copy link
Owner

mcous commented May 10, 2024

Hi @buck06191! I'm opposed to verifyAllWhenMocksCalled on philosophical and technical grounds. See #10 for more details and background.

Philosophical

I think reliance on verifyAllWhenMocksCalled makes your test suite (and, by extension, your code under test) worse by tightly coupling your tests to your implementations and hiding useful design feedback from your tests:

  • Stubs are functions with preconfigured responses to certain calls.
  • Because stubs simply no-op when called with an unconfigured behavior, they exert less coupling force between your tests and your implementation than an assertion, which will fail your test.
  • You test with stubs by injecting them into your code under test and ensuring that the data flows through them correctly. At the end of your test, your code should pop out the correct result. This makes an assertion redundant; if the stub is called incorrectly, your test should fail due to lack of proper result data.
  • If your test does not fail, this is your tests trying to tell you that your code is either not working or not structured in a testable manner.

Technical

Implementating verifyAllWhenMocksCalled requires adding global state to this library, which would then require cleanup. This is not something I'm willing to add to this library, since it would put restrictions on usage and introduce weird cleanup footguns

  • Currently, vitest-when attaches all state to individual vi.fn() mocks for automatic cleanup by Vitest itself
  • You can see the "global cleanup" wart in jest-when, which requires the use of resetAllWhenMocks()

Userland

Not everyone has the same stubbing philosophy as me, and that's ok! While I am unwilling to implement this feature in vitest-when, I am interested in making it so that others, if they so chose, could implement this feature on top of vitest-when in their own suites

Personally, I think verifyAllMWhenMocksCalled is a poor testing practice, but I can see its usefulness as a test debugging tool. To that end, I've been working on #11 to add the ability to inspect individual stubs. I think the debug function should return enough information to determine if an individual stub has been called.

Are there any APIs you could imagine that would help implement a stub registry in your suite - that you would be responsible for managing cleanup of yourself - to give yourself the ability to loop through all your stubs to check them?

@mcous
Copy link
Owner

mcous commented May 11, 2024

I think a fixture like this in your own codebase could work to replicate verifyAllWhenMocksCalled:

// when.ts
import { afterEach, expect } from 'vitest'
import { when as baseWhen } from 'vitest-when'

const mockRegistry = new Set()

export const when: typeof baseWhen = (spy, options) => {
  const result = baseWhen(spy, options)
  mockRegistry.add(spy)
  return result
}

afterEach(() => {
  const mocks = [...mockRegistry]
  mockRegistry.clear()

  for (const mock of mocks) {
    expect(mock).toHaveBeenCalled()
  }
})

Then, in your tests, import when from your fixture file instead of directly from vitest-when

@mcous
Copy link
Owner

mcous commented May 13, 2024

@buck06191 thanks for taking the time to write this request! After giving it some additional thought over the weekend - and after landing #11 - I don't think this feature is a good fit for this library. I'd like to keep vitest-when pretty laser-focused on adding a conditional stubbing API to vi.fn(). I think call assertions and more frameworky features - like tracking the state of all mocks - are best left to userland and/or vitest itself.

Let me know if the above example is able to get you where you need to go, or if there are additional stub-level APIs that could be added to help you implement what you're trying to do

@mcous mcous closed this as not planned Won't fix, can't repro, duplicate, stale May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants