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 mock issue when running tests #44

Open
Faboslav opened this issue Nov 4, 2024 · 11 comments
Open

Vitest mock issue when running tests #44

Faboslav opened this issue Nov 4, 2024 · 11 comments
Assignees

Comments

@Faboslav
Copy link

Faboslav commented Nov 4, 2024

Hello there,

i migrated the project from tsyringe, and it works perfectly fine.
When running vitest following occurs when i try to mock a dependency, which is normally injected in the constructor:

TypeError: Cannot read properties of undefined (reading 'provide')
 ❯ Container.bind node_modules/@needle-di/core/src/container.ts:92:73

Screenshot 2024-11-04 at 6 50 19

Mentioned part of the code in test:

  const mockScenarioService = mockDeep<ScenarioService>();
  const mockSessionScenarioProgressProvider = mockDeep<SessionScenarioProgressProvider>();
  let sessionStepGuard: SessionStepGuard;

  beforeEach(() => {
    mockReset(mockScenarioService);
    mockReset(mockSessionScenarioProgressProvider);
    sessionStepGuard = new SessionStepGuard(mockScenarioService, mockSessionScenarioProgressProvider);
  });

Can this be due to some invalid or missing setting, like target of ES2022 or something like that?

@Faboslav
Copy link
Author

Faboslav commented Nov 4, 2024

Okay, so i found out, this happens, when test uses class which uses any kind of InjectionToken inside it in its injects, for example:

export const SCENARIO_REPOSITORY = new InjectionToken<ScenarioRepository>('SCENARIO_REPOSITORY');
  public constructor(
    private readonly scenarioRepository: ScenarioRepository = inject(SCENARIO_REPOSITORY),
  ) {}

which works in the app, but in the test its problematic, but i dont know why.

Trying string instead of token works for me:

private readonly scenarioRepository: ScenarioRepository = inject('ScenarioRepository'),

@dirkluijk
Copy link
Collaborator

dirkluijk commented Nov 4, 2024

Thanks for reporting this issue. Let's see if we can reproduce it.
From your first comment, I'd say it's because SessionStepGuard is undefined somehow, but I am still figuring out why.

Can you clone this StackBlitz and try to reproduce it in there? Alternatively, you can share me a reproduction in a Github repository.

@dirkluijk dirkluijk self-assigned this Nov 4, 2024
@Faboslav
Copy link
Author

Faboslav commented Nov 7, 2024

Sorry, i was little bit busy, i will try to do some more debugging later :).

@dirkluijk
Copy link
Collaborator

Let me know, I am motivated to help you out here. ;)

@Faboslav
Copy link
Author

Hello, sorry for the huge delay again, i am back at the project, I did some more testing and it seems to work if i follow the "auto-binding", if i have everything related "manually" binded to the container, it throws the mentioned error with vitest.

@dirkluijk
Copy link
Collaborator

No problem!

Hm, only thing I can imagine is some kind of cyclic dependency or something. Still interested in a small example, if you have the time, it would be very helpful to prevent this issue for others. 😎

@Faboslav
Copy link
Author

Faboslav commented Jan 16, 2025

I can actually provide my "playground" project: https://github.com/octotravel/validator/tree/feat/monorepo. I still cant get tokens to work, for example in:

https://github.com/octotravel/validator/blob/feat/monorepo/backend/src/common/database/Database.ts
(container is here: https://github.com/octotravel/validator/blob/feat/monorepo/backend/src/common/di/container.ts)

There is the following line currently commented out:

// private readonly exceptionLogger = inject(EXCEPTION_LOGGER),

With current state when i run npm run test (docker with db needs to be running too) it works, but when i remove the commend, vitest wont even run and output anything, if i reconfigure the binding just to string and update the inject, like the following:

private readonly exceptionLogger = inject('ExceptionLogger'),

It works again.

Since this migration from tsyringe is a long term PR its possible that i am just overlooking something in the project or in your docs :).

@dirkluijk
Copy link
Collaborator

I haven't tested it, but my gut feeling it has to do with cyclic dependencies. What if you move the injection token EXCEPTION_LOGGER to its own file?

@Faboslav
Copy link
Author

Faboslav commented Jan 16, 2025

I will try that and let you know, but if that's the case, it would be good to do some extra logging by default or enable some kind of "debug/verbose" mode on the container.

Update: moving the token and/or bind to its own file doesnt help in this case.

@dirkluijk
Copy link
Collaborator

I will try to dive deeper in your case later this week!

@Faboslav
Copy link
Author

Thank you! No worries, its not some priority on my side anyway

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