test(server): make testing more isolated (#4290)

This commit is contained in:
LongYinan
2023-09-08 13:02:27 -07:00
committed by GitHub
parent a97fd486c3
commit 58a935b31d
4 changed files with 49 additions and 32 deletions

View File

@@ -1,6 +1,6 @@
import { Global, Module } from '@nestjs/common'; import { Global, Module } from '@nestjs/common';
import { SessionService } from '../../session'; import { SessionModule } from '../../session';
import { MAILER, MailService } from './mailer'; import { MAILER, MailService } from './mailer';
import { NextAuthController } from './next-auth.controller'; import { NextAuthController } from './next-auth.controller';
import { NextAuthOptionsProvider } from './next-auth-options'; import { NextAuthOptionsProvider } from './next-auth-options';
@@ -9,9 +9,9 @@ import { AuthService } from './service';
@Global() @Global()
@Module({ @Module({
imports: [SessionModule],
providers: [ providers: [
AuthService, AuthService,
SessionService,
AuthResolver, AuthResolver,
NextAuthOptionsProvider, NextAuthOptionsProvider,
MAILER, MAILER,

View File

@@ -1,19 +1,23 @@
import KeyvRedis from '@keyv/redis'; import KeyvRedis from '@keyv/redis';
import { Global, Injectable, Module } from '@nestjs/common'; import {
FactoryProvider,
Global,
Inject,
Injectable,
Module,
} from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import Keyv from 'keyv'; import Keyv from 'keyv';
import { Config } from './config'; import { Config } from './config';
@Injectable() export const KeyvProvide = Symbol('KeyvProvide');
export class SessionService {
private readonly cache: Keyv;
private readonly prefix = 'session:';
private readonly sessionTtl = 30 * 60 * 1000; // 30 min
constructor(protected readonly config: Config) { export const KeyvProvider: FactoryProvider<Keyv> = {
provide: KeyvProvide,
useFactory(config: Config) {
if (config.redis.enabled) { if (config.redis.enabled) {
this.cache = new Keyv({ return new Keyv({
store: new KeyvRedis( store: new KeyvRedis(
new Redis(config.redis.port, config.redis.host, { new Redis(config.redis.port, config.redis.host, {
username: config.redis.username, username: config.redis.username,
@@ -23,9 +27,18 @@ export class SessionService {
), ),
}); });
} else { } else {
this.cache = new Keyv(); return new Keyv();
} }
} },
inject: [Config],
};
@Injectable()
export class SessionService {
private readonly prefix = 'session:';
private readonly sessionTtl = 30 * 60 * 1000; // 30 min
constructor(@Inject(KeyvProvide) private readonly cache: Keyv) {}
/** /**
* get session * get session
@@ -54,7 +67,7 @@ export class SessionService {
@Global() @Global()
@Module({ @Module({
providers: [SessionService], providers: [KeyvProvider, SessionService],
exports: [SessionService], exports: [KeyvProvider, SessionService],
}) })
export class SessionModule {} export class SessionModule {}

View File

@@ -1,40 +1,44 @@
/// <reference types="../global.d.ts" /> /// <reference types="../global.d.ts" />
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { PrismaClient } from '@prisma/client'; import ava, { TestFn } from 'ava';
import test from 'ava';
import { ConfigModule } from '../config'; import { ConfigModule } from '../config';
import { SessionModule, SessionService } from '../session'; import { SessionModule, SessionService } from '../session';
let session: SessionService; const test = ava as TestFn<{
let module: TestingModule; session: SessionService;
app: TestingModule;
}>;
// cleanup database before each test test.beforeEach(async t => {
test.beforeEach(async () => { const module = await Test.createTestingModule({
const client = new PrismaClient(); imports: [
await client.$connect(); ConfigModule.forRoot({
await client.user.deleteMany({}); redis: {
await client.$disconnect(); enabled: false,
}); },
}),
test.beforeEach(async () => { SessionModule,
module = await Test.createTestingModule({ ],
imports: [ConfigModule.forRoot(), SessionModule],
}).compile(); }).compile();
session = module.get(SessionService); const session = module.get(SessionService);
t.context.app = module;
t.context.session = session;
}); });
test.afterEach(async () => { test.afterEach(async t => {
await module.close(); await t.context.app.close();
}); });
test('should be able to set session', async t => { test('should be able to set session', async t => {
const { session } = t.context;
await session.set('test', 'value'); await session.set('test', 'value');
t.is(await session.get('test'), 'value'); t.is(await session.get('test'), 'value');
}); });
test('should be expired by ttl', async t => { test('should be expired by ttl', async t => {
const { session } = t.context;
await session.set('test', 'value', 100); await session.set('test', 'value', 100);
t.is(await session.get('test'), 'value'); t.is(await session.get('test'), 'value');
await new Promise(resolve => setTimeout(resolve, 500)); await new Promise(resolve => setTimeout(resolve, 500));