Nest: Can't overrideProvider with any mock in e2e tests

Created on 30 May 2019  路  17Comments  路  Source: nestjs/nest

Bug Report

Current behavior

I tried 3 librairies for mocking a dependency X: Sinon, Typemoq and Ts-Mockito.
When I'm using the @nestjs/testing module to create a testing module and I want to override a provider, the @nestjs/testing doesn't work with all 3 mocking librairies. It wont boot. Out of the 3, only sinon's mock works.

Input Code

this is a repository that reproduce the problem.
https://github.com/Christo676/nestjs-e2e-mock

import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from '@main/app.module';
import * as sinon from 'sinon';
// import * as TypeMoq from 'typemoq';
import { SomeDependency } from '@main/provider/some-dependency';
import { SinonStubbedInstance } from 'sinon';
// import {instance, mock, when} from 'ts-mockito';

describe('Actuator', (): void => {
    let app: INestApplication;
    //Sinon
    let mockedSomeDependency: SinonStubbedInstance<SomeDependency>;

    //Typemoq
    // let mockedSomeDependency: TypeMoq.IMock<SomeDependency>;

    //Ts-Mockito
    // let mockedSomeDependency: SomeDependency;
    // let instanceSomeDependency: SomeDependency;

    beforeAll(
        async (): Promise<void> => {
            //Sinon
            mockedSomeDependency = sinon.createStubInstance(SomeDependency);
            mockedSomeDependency.getHelloWorld.returns(Promise.resolve('hello nestjs'));

            //Typemoq
            // mockedSomeDependency = TypeMoq.Mock.ofType<SomeDependency>();
            // mockedSomeDependency.setup((someDependency): Promise<string> => someDependency.getHelloWorld()).returns(async () => 'hello nestjs');

            //Ts-Mockito
            // mockedSomeDependency = mock(SomeDependency);
            // when(mockedSomeDependency.getHelloWorld()).thenReturn(Promise.resolve('hello nestjs'));
            // instanceSomeDependency = instance(mockedSomeDependency);

            const module = await Test.createTestingModule({
                imports: [AppModule]
            })
                //Sinon
                .overrideProvider('dependency')
                .useValue(mockedSomeDependency)

                //Typemoq
                //     .overrideProvider('dependency')
                //     .useValue(mockedSomeDependency.object)

                //Ts-Mockito
                //     .overrideProvider('dependency')
                //     .useValue(instanceSomeDependency)
                .compile();

            app = module.createNestApplication();
            await app.init();
        }
    );

    afterAll(
        async (): Promise<void> => {
            await app.close();
        }
    );

    it('should return hello nestjs instead of hello world', async (): Promise<Test> => {
        return await request
            .agent(app.getHttpServer())
            .get('/api/v1/test/greet')
            .expect(200)
            .expect('hello nestjs');
    });
});

Expected behavior

I expect the NestJs testing module to take in all mocks and to override the provider targeted.

Possible Solution

Environment


Nest version: 6.2.4

For Tooling issues:
- Node version: v11.14.0
- Platform:  Windows 10

Others:
IDE: IntelliJ Ultimate 2019
needs triage

Most helpful comment

Hi @Christo676,
It seems that there is some weird issue with Proxies & Jest & NestJS & mocking libraries & and Promise.all() used at the same time (jest just hangs out).

There is a very simple workaround for this though:

//Typemoq
//.overrideProvider('dependency')
//.useValue(Object.assign({}, mockedSomeDependency.object))

//Ts-Mockito
.overrideProvider('dependency')
.useValue(Object.assign({}, instanceSomeDependency))

(add Object.assign())

All 17 comments

Just to confirm that I properly understand your issue. Is sinon actually working well, whereas other ones don't work at all?

Exactly

I'm not sure if this issue is really related to Nest ecosystem. If sinon actually works fine, there is no reason for other ones to behave differently. We have recently fixed one issue with override (6.3.0 release), could you check if it fixed your issue?

I will update my project tomorrow and see if it fixes the problem. I will let you know.

I updated my repository with the latest version (6.3.1) and it did't change anything. Only sinon mocks work.

I have this same problem using ts-mockito

Hi @Christo676,
It seems that there is some weird issue with Proxies & Jest & NestJS & mocking libraries & and Promise.all() used at the same time (jest just hangs out).

There is a very simple workaround for this though:

//Typemoq
//.overrideProvider('dependency')
//.useValue(Object.assign({}, mockedSomeDependency.object))

//Ts-Mockito
.overrideProvider('dependency')
.useValue(Object.assign({}, instanceSomeDependency))

(add Object.assign())

Even if there is a workaround, why do you close this issue? It is still an issue! Why don't you guys implement a solution or put the workaround in your librairy so the rest of the world don't have to?

This issue is not caused by NestJS.

Fine it is not cause by NestJs, but it affects the user experience about NestJs. If there was an issue with the integration between NestJs and Express or NestJs and Fastify, I'm pretty sure you guys would do stuff to make it work which will lead to better user experience and better community adoption, even though its not NestJs fault. I believe this scenario is the same. Don't get me wrong, I love what you guys do and I appreciate it. That is why I would like to see that product being more adopted.

Hardcoding additional checks if Proxy object has been created by either ts-mockito or typemoq sounds quite strange. I'd love to have better user experience with every existing mocking library, but in this case, we'd have to tie the core package to 3rd-party libraries.

Correct me if i'm wrong but Proxy is a core object of Nodejs, not an object from a third party librairy

Yes, it is. I didn't say that we'd have to add just Proxy comparison check.

I think it would be a good idea and it wouldn't cost much, what do you think?

Let me clarify. I'm not saying that we would have to add just Proxy check, but a check if Proxy object has been created by either ts-mockito or typemoq. Regular proxies are compatible with Nest.

Okay you are saying that ts-mockito's and typemoq's mock are not instance of Proxy? And it is their own object? If it is the case I understand

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marshall007 picture marshall007  路  3Comments

breitsmiley picture breitsmiley  路  3Comments

rlesniak picture rlesniak  路  3Comments

FranciZ picture FranciZ  路  3Comments

cojack picture cojack  路  3Comments