• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

714
Views
NestJS e2e test mock Session decorator

I'm trying to write an e2e test with supertest where my controller actually makes use of the @Session() decorator. I however don't want to have the full burden of initiating a session with db connection and so on so my app in the test does not actually initialize the session.

I'd instead like to mock away the data provided by the Decorator in the first place and replace it with static data. I can't really find a solution as to how to realize this however.

Sample from controller:

@Get('/user/me')
public async getMe(@Session() session: Record<string, unknown>) {
  if (!session?.user) {
    throw new InternalServerErrorException();
  }
  return session.user;
}

What I'd ideally like the mock to look like:

jest.mock(Session, jest.fn().mockImplementation(() => {
  return { user: { name: "test user" } };
})

however this won't work.

According to the official TypeScript documentation Parameter decorators can only be used to observe that a parameter has been set on a particular method. As this is not actually what's happening when using the @Session() decorator I tried having a look at the source code of how nestjs actually implements these decorators and I'm having at some trouble understanding it correctly.

If I'm not mistaking it seems like the decorator writes some metadata another decorator (probably @Get() in this case?) can make use of and extract the necessary data based on that.

I'm a little confused as to how to test this properly so I'd be very thankful for some advice :)

===========================================================================

Update: I will now go ahead and instead of mocking the Session decorator itself mock the req.session while setting up my app in beforeAll() hook. Therefore I chose the following solution:

app.use((req, res, next) => {
    req.session = {
      user: {
        firstName: 'Max',
        lastName: 'Mustermann',
      },
    };
    next();
});

I'll still be very happy in case someone knows a better solution.

about 3 years ago · Santiago Trujillo
1 answers
Answer question

0

To solve the problem create a common function to which creates the nest application for e2e and provided hooks config which enables overriding of testing module and application middleware injection of express

Common Setup function


/**
 * Hook for overriding the testing module
 */
export type TestingModuleCreatePreHook = (
  moduleBuilder: TestingModuleBuilder,
) => TestingModuleBuilder;


/**
 * Hook for adding items to nest application
 */
export type TestingAppCreatePreHook = (
  app: NestExpressApplication,
) => Promise<void>;

/**
 * Sets basic e2e testing module of app
 */
export async function basicE2eSetup(
  config: {
    moduleBuilderHook?: TestingModuleCreatePreHook;
    appInitHook?: TestingAppCreatePreHook;
  } = {},
): Promise<[NestExpressApplication, TestingModule]> {
  let moduleBuilder: TestingModuleBuilder = Test.createTestingModule({
    imports: [AppModule],
  });

  if (!!config.moduleBuilderHook) {
    moduleBuilder = config.moduleBuilderHook(moduleBuilder);
  }

  const moduleFixture: TestingModule = await moduleBuilder.compile();
  const app = moduleFixture.createNestApplication<NestExpressApplication>();  

  if (config.appInitHook) {
    await config.appInitHook(app);
  }

  return [await app.init(), moduleFixture];
}

Usage


describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    [app] = await basicE2eSetup({
      moduleBuilderHook: (moduleBuilder) => {
        // your overrides go here
        // Refer: https://docs.nestjs.com/fundamentals/testing#end-to-end-testing
        // eg: moduleBuilder.overrideProvider(ProviderName).useValue(value)
        return moduleBuilder;
      },
      appInitHook: async (app) => {
        const result = await someAction();
        // or get some service from app 
        // eg: const service = app.get<YourService>(YourService)
        app.use((req, res, next) => {
          // do something with request of response object
          next();
        })
      } 
    });
  });

  it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect((res) => {
        expect(res.text).toContain('Hi There');
      });
  });
});

about 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error