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 doesn't work properly with @nestjs/testing #708

Closed
6 tasks done
wight554 opened this issue Feb 9, 2022 · 19 comments
Closed
6 tasks done

vitest doesn't work properly with @nestjs/testing #708

wight554 opened this issue Feb 9, 2022 · 19 comments
Labels

Comments

@wight554
Copy link

wight554 commented Feb 9, 2022

Describe the bug

Running vitest on any sample app from https://github.com/nestjs/nest/tree/master/sample won't run well with testing modules like this

    const module: TestingModule = await Test.createTestingModule({
      controllers: [CatsController],
      providers: [
        {
          provide: CatsService,
          useValue: {
            create: vi.fn().mockResolvedValue(createCatDto),
          },
        },
      ],
    }).compile();

and leads to errors like this:

 FAIL  src/users/users.controller.spec.ts > UsersController > create() > should create a user
TypeError: Cannot read properties of undefined (reading 'create')
 ❯ UsersController.create src/users/users.controller.ts:12:29
     10|   @Post()
     11|   create(@Body() createUserDto: CreateUserDto): Promise<User> {
     12|     return this.usersService.create(createUserDto);
       |                             ^
     13|   }
     14| 

Might be related to nestjs itself, but runs well on jest

Reproduction

https://github.com/wight554/vitest-nestjs-testing

System Info

System:
    OS: macOS 12.2
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 118.12 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.13.2 - ~/.nvm/versions/node/v16.13.2/bin/node
    Yarn: 1.22.15 - ~/.nvm/versions/node/v16.13.2/bin/yarn
    npm: 8.1.2 - ~/.nvm/versions/node/v16.13.2/bin/npm
    Watchman: 2021.10.04.00 - /usr/local/bin/watchman
  Browsers:
    Chrome: 98.0.4758.80
    Edge: 97.0.1072.76
    Safari: 15.3
  npmPackages:
    vite: ^2.7.13 => 2.7.13 
    vitest: ^0.2.8 => 0.2.8

Used Package Manager

npm

Validations

@wight554
Copy link
Author

wight554 commented Feb 9, 2022

Added reproduction repo https://github.com/wight554/vitest-nestjs-testing

npx vitest run src/users/users.controller.vitest.spec.ts returns

 ❯ src/users/users.controller.vitest.spec.ts (5)
   ❯ UsersController (5)
     √ should be defined
     ❯ create() (1)
       × should create a user
     ❯ findAll() (1)
       × should find all users 
     ❯ findOne() (1)
       × should find a user
     ❯ remove() (1)
       × should remove the user

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 4 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/users/users.controller.vitest.spec.ts > UsersController > create() > should create a user
TypeError: Cannot read properties of undefined (reading 'create')
 ❯ UsersController.create src/users/users.controller.ts:12:29
     10|   @Post()
     11|   create(@Body() createUserDto: CreateUserDto): Promise<User> {
     12|     return this.usersService.create(createUserDto);
       |                             ^
     13|   }
     14| 
 ❯ src/users/users.controller.vitest.spec.ts:63:29

while npx jest src/users/users.controller.spec.ts returns

 PASS  src/users/users.controller.spec.ts
  UsersController
    ✓ should be defined (11 ms)
    create()
      ✓ should create a user (5 ms)
    findAll()
      ✓ should find all users  (6 ms)
    findOne()
      ✓ should find a user (3 ms)
    remove()
      ✓ should remove the user (3 ms)

Test Suites: 1 passed, 1 total
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        3.21 s
Ran all test suites matching /src\/users\/users.controller.spec.ts/i.

From what I've seen in @nestjs/testing it doesn't rely on specific testing framework, so it seems to be vitest issue

@wight554
Copy link
Author

wight554 commented Feb 9, 2022

another example:
running this test module in jest will output result, while vite never enters .useMocker()

    const app: TestingModule = await Test.createTestingModule({
      controllers: [UsersController],
    }).useMocker(token => {
      if(token === UsersService) {
        console.log('token is UsersService', token === UsersService)
      }
    }).compile();

also I've noticed that this code:

{
  provide: token,
  useValue: {}
}

would work if you use some token getter (like getModelToken from sequelize) from example src/users/users.service.spec.ts
this also works with mongoose like here https://github.com/wight554/blog-template/blob/master/test/server/post/PostService.test.ts#L72

@wight554
Copy link
Author

wight554 commented Feb 9, 2022

tested with mocha - works fine as well, so issue is definitely not on nestjs side
upd. works fine with https://www.npmjs.com/package/intern as well

@wight554 wight554 changed the title Vitest doesn't play well with nestjs testing module vitest doesn't work properly with @nestjs/testing Feb 9, 2022
@sheremet-va sheremet-va added bug good first issue Good for newcomers labels Feb 9, 2022
@wight554
Copy link
Author

Just to clarify, still fails on [email protected]

@sheremet-va sheremet-va added the help wanted Extra attention is needed label Feb 17, 2022
@wight554
Copy link
Author

[email protected] fails too
There's no issue in binding value to UserService, but binding UserService to UserController
Something related to context most likely

@wight554
Copy link
Author

@sheremet-va got answer from nest team member
nestjs/nest#9228 (comment)
Is there any workaround, maybe compiler option/fallback?

@jmcdo29
Copy link

jmcdo29 commented Feb 18, 2022

I don't know much about vite or how it's using esbuild under the hood, but if it is using the async API of esbuild you can use a plugin like esbuild-plugin-tsc to make use of decorators, and the typescript compiler specifically on files that use decorators, but other than that, I know it's out of scope for esbuild to support the emitDecoratorMetadata flag

@wight554
Copy link
Author

wight554 commented Feb 18, 2022

As I see vite doesn't support esbuild plugins, but allows to disable esbuild in favour of rollup, and rollup has full set of options. E.g. https://github.com/axe-me/vite-plugin-node uses swc for nestjs instead of esbuild
This approach can't be used for vitest only because it doesn't let you to access esbuild/build options in test scope

@wight554
Copy link
Author

I've created working example with swc:
wight554/vitest-nestjs-testing@9e4d1e5
At this point, there are 2 ways to workaround this issue:

  1. Open new issue at vite for supporting esbuild plugins (better option)
  2. Allow overriding these settings from test scope
    It's also possible to use separate vite config file for vitest, but I don't feel like it is a good option while having test scope

@wight554
Copy link
Author

wight554 commented Feb 18, 2022

Oh I see, vite has some kind of esbuild plugin support, but vitest can't benefit from it
Can you please revisit #269 ?

@sheremet-va
Copy link
Member

Oh I see, vite has some kind of esbuild plugin support, but vitest can't benefit from it Can you please revisit #269 ?

It was closed because we don't use optimizeDeps, since we are not prebundling for Node. There is esbuild options, but it doesn't support plugins. Maybe we can ask in Vite issues to support it?

@sheremet-va
Copy link
Member

I would also prefer using swc in your case, since it's faster than esbuild plugin. I heard Vite team discussed using it at one point? /cc @patak-dev

@wight554
Copy link
Author

Oh I see, vite has some kind of esbuild plugin support, but vitest can't benefit from it Can you please revisit #269 ?

It was closed because we don't use optimizeDeps, since we are not prebundling for Node. There is esbuild options, but it doesn't support plugins. Maybe we can ask in Vite issues to support it?

Don't think they'll implement additional way to use plugins just for vitest that's lacking it. But if you don't mind, can you do this? I don't think I'll be able to give enough argumentation on why it's needed

@wight554
Copy link
Author

I would also prefer using swc in your case, since it's faster than esbuild plugin. I heard Vite team discussed using it at one point? /cc @patak-dev

swc is a decent choice, but that implies using another heavyweight compiler in project just for tests. Also it's handled by rollup plugin which makes compilation process more complicated. esbuild has a way to handle this issue, so using it would be preferable imo

@sheremet-va sheremet-va added upstream and removed bug help wanted Extra attention is needed good first issue Good for newcomers labels May 5, 2022
@sheremet-va
Copy link
Member

Changing label to upstream, because we are limited by the Vite api. You can open an issue in Vite repo to allow passing esbuild plugins.

@sheremet-va
Copy link
Member

After writing the previous message, I decided to look up how Vite uses esbuild. Turns out, Vite uses transform function of esbuild that transforms a single file, and doesn't support plugins.

Plugins for esbuild are supported only when using esbuild as a bundler, so Vite actually cannot do anything about it. You can try bundle your files with esbuild and run tests against them, although I don't think it will be a good DX, but there is nothing Vitest can do to fix this.

To summarize, you can either:

  • Build files with esbuild as a bundler (which might require a lot of custom options), and run tests against it
  • Use swc plugin

Closing the issue, since it is out of scope of Vitest.

@V-ed
Copy link

V-ed commented May 5, 2022

Use swc plugin

With this recommendation, I installed https://github.com/egoist/unplugin-swc and it seems to work fine indeed!

Hoping the decorator proposal progresses faster so esbuild implements it or that vite supports running esbuild plugins so we could use esbuild-plugin-tsc, using esbuild's fast transpilation while testing with Decorators!

futchitwo added a commit to futchitwo/misskey that referenced this issue Feb 9, 2023
@BrainCrumbz
Copy link

@V-ed do you have any example on how to integrate SWC into vitest, instead of the default esbuild compiler? We could not find many info about it.
Thanks

@V-ed
Copy link

V-ed commented Apr 3, 2023

@V-ed do you have any example on how to integrate SWC into vitest, instead of the default esbuild compiler? We could not find many info about it. Thanks

I haven't done anything else than what is said in the readme of the repo (https://github.com/egoist/unplugin-swc) : Install it using your package manager and use the vite plugin in your configuration (in my case, in the vitest.config.ts file).

If it's still not working / there's any other issue, I'm afraid I can't really help and you should probably raise another issue with your problem.

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

No branches or pull requests

5 participants