Using test database when e2e-testing NestJS - javascript

In this project, it uses NestJS along with TypeORM. For real API requests, CRUD operation is being operated on MySQL(which is using AWS RDS).
Now I am trying to use SQLite(In-Memory) to test API results.
I successfully implemented this in Unit Test, as the code below.
First, below is create-memory-db.ts, which returns a connection to in-memory SQLite database.
type Entity = Function | string | EntitySchema<any>;
export async function createMemoryDB(entities: Entity[]) {
return createConnection({
type: 'sqlite',
database: ':memory:',
entities,
logging: false,
synchronize: true,
});
}
And by using the exported function above, I successfully ran Unit test, like below.
describe('UserService Logic Test', () => {
let userService: UserService;
let connection: Connection;
let userRepository: Repository<User>;
beforeAll(async () => {
connection = await createMemoryDB([User]);
userRepository = await connection.getRepository(User);
userService = new UserService(userRepository);
});
afterAll(async () => {
await connection.close();
});
afterEach(async () => {
await userRepository.query('DELETE FROM users');
});
// testing codes.
});
I am trying to do the same thing on e2e tests. I tried below code.
// user.e2e-spec.ts
describe('UserController (e2e)', () => {
let userController: UserController;
let userService: UserService;
let userRepository: Repository<User>;
let connection: Connection;
let app: INestApplication;
const NAME = 'NAME';
const EMAIL = 'test#test.com';
const PASSWORD = '12345asbcd';
beforeAll(async () => {
connection = await createMemoryDB([User]);
userRepository = await connection.getRepository(User);
userService = new UserService(userRepository);
userController = new UserController(userService);
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [],
controllers: [UserController],
providers: [UserService],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await connection.close();
});
afterEach(async () => {
// await userRepository.query('DELETE FROM users');
});
it('[POST] /user : Response is OK if conditions are right', () => {
const dto = new UserCreateDto();
dto.name = NAME;
dto.email = EMAIL;
dto.password = PASSWORD;
return request(app.getHttpServer())
.post('/user')
.send(JSON.stringify(dto))
.expect(HttpStatus.CREATED);
});
});
I cannot create UserModule since it doesn't have a constructor with Connection parameter.
The code itself has no compile error, but gets results below when e2e test is executed.
Nest can't resolve dependencies of the UserService (?). Please make sure that the argument UserRepository at index[0] is available in the RootTestModule context.
Potential solutions:
- If UserRepository is a provider, is it part of the current RootTestModule?
- If UserRepository is exported from a seperate #Module, is that module imported within RootTestModule?
#Module({
imports: [/* The module containing UserRepository */]
})
TypeError: Cannot read property 'getHttpServer' of undefined.
Any help would be greatly appreciated. Thanks :)
UPDATE : New error occured after trying below.
describe('UserController (e2e)', () => {
let userService: UserService;
let userRepository: Repository<User>;
let connection: Connection;
let app: INestApplication;
const NAME = 'NAME';
const EMAIL = 'test#test.com';
const PASSWORD = '12345asbcd';
beforeAll(async () => {
connection = await createMemoryDB([User]);
userRepository = await connection.getRepository(User);
userService = new UserService(userRepository);
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [UserModule],
})
.overrideProvider(UserService)
.useClass(userService)
.compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await connection.close();
});
afterEach(async () => {
await userRepository.query('DELETE FROM users');
});
it('[POST] /user : Response is OK if conditions are right', async () => {
const dto = new UserCreateDto();
dto.name = NAME;
dto.email = EMAIL;
dto.password = PASSWORD;
const result = await request(app.getHttpServer())
.post('/user')
.send(JSON.stringify(dto))
.expect({ status: HttpStatus.CREATED });
});
});
I checked if query is working, and was able to see that it is using SQLite database as I wanted. But new error appeared in console.
TypeError: metatype is not a constructor.
TypeError: Cannot read property 'getHttpServer' of undefined.

Okay, I solved this issue by using TypeOrm.forRoot() inside the imports field of Test.createTestingModule. Below is how I did it.
describe('UserController (e2e)', () => {
let userService: UserService;
let userRepository: Repository<User>;
let app: INestApplication;
const NAME = 'NAME';
const EMAIL = 'test#test.com';
const PASSWORD = '12345asbcd';
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
UserModule,
TypeOrmModule.forRoot({
type: 'sqlite',
database: ':memory:',
entities: [User],
logging: true,
synchronize: true,
}),
],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
userRepository = moduleFixture.get('UserRepository');
userService = new UserService(userRepository);
});
afterAll(async () => {
await app.close();
});
afterEach(async () => {
await userRepository.query('DELETE FROM users');
});
});

For those looking for setup e2e tests that hit endpoints and assert the response body, you can do something like this:
// app.module.ts
#Module({
imports: [
TypeOrmModule.forRootAsync({
useFactory: async (configService: ConfigService) => {
if (process.env.APPLICATION_ENV === 'test') {
return {
type: 'sqlite',
database: ':memory:',
entities: [Entity],
synchronize: true,
}
}
return {
// your default options
};
},
}),
]
})

Related

Proxyquire not calling inner functions (npm modules) and does not work with classes properly

Where am i going wrong here?
Using mocha, chai, sinon and proxyquire for an express server and sequelize ORM linked with a postgres database
I am trying to test a login controller route from my express server
Before I show the file which I want to run my test on here is what "../services/authService.js" file looks like
../services/authService
const UserService = require("./userService");
module.exports = class AuthService extends UserService {
};
// so UserService will have the method findByEmail
// UserService class looks like this and it is coming from another file require("./userService.js) as stated above
/*
class UserService {
async findByEmail(email) {
try {
const user = await User.findOne({ where: { email: email }});
if (user) {
return user;
}
throw new Error("User not found");
} catch (err) {
err.code = 404;
throw err
}
}
}
*/
And here is the auth-controller.js file which I want to run the test on
auth-controller.js
const bcrypt = require('bcryptjs');
const AuthService = require("../services/authService"); // is a class which extends from another calls see the code above
const authService = new AuthService();
const jwtGenerator = require('../utils/jwtGenerator');
const createError = require("http-errors");
exports.loginRoute = async (req, res, next) => {
try {
req.body.password = String(req.body.password);
// db query trying to force a sinon.stub to resolve a fake value. But code wont pass here hence 500 error
const userQuery = await authService.findByEmail(req.body.email);
const compare = await bcrypt.compare(req.body.password, userQuery.password);
if (!compare) throw createError(401, 'Incorrect password.');
const user = {
id: userQuery.id, role: userQuery.is_admin ? "Administrator" : "User", email: userQuery.email, Authorized: true
}
const token = jwtGenerator(user);
return res
.cookie("access_token", token, {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
}).status(200).json({ message: "Logged in successfully 😊 👌", user, token });
} catch (error) {
next(error);
}
}
This code works in production but I cannot seem to test it. I used proxyquire to require the modules that the function uses. I have a big problem in making proxyquire work when it comes to my class AuthService here is my test file. As proxyquire is not working with classes some how. proxyquire is not using make AuthServiceMock at all cant figure out why.
First of these are my helper variables which I will use in the test file
../test-utils/user-helper
const createAccessToken = (payload) => jwt.sign(payload, TOKEN, {expiresIn: "1h"});
let loginDetail = {
email: "admin#test.com",
password: "123456"
};
let loginAdminUser = {
id: 1,
email: "admin#test.com",
password: "123456",
is_admin: true
}
const loginUser = {
id: 1,
email: "admin#test.com",
password: "123456",
is_admin: true
}
const adminUser = {
id: 1,
email: 'admin#test.com',
password: '123456',
is_admin: true,
first_name: 'john',
last_name: 'doe',
created_at: "2020-06-26T09:31:36.630Z",
updated_at: "2020-06-26T09:31:49.627Z"
}
module.exports = {
createAccessToken,
loginDetail,
loginAdminUser,
loginUser,
adminUser
}
And here is the test file I placed comments espcially around proxyquire when I am trying to use it as this is giving me some issues when it comes to using it with classes. And as well it is not calling mocked/stubbed npm modules for some reason
auth-controller.spec.js
"use strict";
const _ = require("lodash");
const path = require("path");
const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
const chai = require("chai");
const { expect } = chai;
const sinon = require("sinon");
const sinonChai = require("sinon-chai");
chai.use(sinonChai);
// const AuthServiceOriginalClass = require("../../services/authService"); If i use this directly in proxyquire it calls the original class
const { createAccessToken, loginDetail, loginAdminUser, loginUser, adminUser } = require("../test-utils/user-helper");
const controllerPath = path.resolve('./controllers/authController.js');
describe("login route", () => {
let proxy, authService, bcryptStub, fakeCallback, fakeReq, fakeRes, fakeNext, resolveFn, token;
let result, bcryptStubbing, response;
class UserServiceMock {
async findByEmail(email) {
try {
if (email) {
return loginAdminUser;
}
} catch (error) {
throw error;
}
}
}
class AuthServiceMock extends UserServiceMock {};
bcryptStub = {
compare: function() { return true }
};
let tokeen = (kk) => {
return createAccessToken(kk);
}
// token = sinon.mock(createAccessToken(loginAdminUser)); // ?? which 1 to use?
token = sinon.spy(createAccessToken); // ?? which 1 to use?
// token = sinon.stub(createAccessToken) ?? which 1 to use?
proxy = proxyquire(controllerPath, {
"../services/authService.js": AuthServiceMock, // seems like this is not called at all
// "../services/authService.js": AuthServiceOriginalClass, // commented out if use this instead it calls the original class instant
"bcryptjs": bcryptStub,
"../utils/jwtGenerator": token,
// "#noCallThru": true // keep on or off?
});
before("Stub my methods", () => {
authService = new AuthServiceMock();
// If I call the entire loginRoute I want this stub authTry to be called inside of it and resolve that object value
authTry = sinon.stub(authService, "findByEmail").withArgs(loginDetail.email).resolves(loginAdminUser);
sinon.stub(bcryptStub, "compare").resolves(true); // force it to return true as that seems to be like the code of authController.js
// sinon.stub(token, "createAccessToken")
});
before("call the function loginRoute", async () => {
// fakeCallback = new Promise((res, rej) => {
// resolveFn = res
// });
fakeReq = {
body: {
email: loginDetail.email,
password: loginDetail.password
}
};
fakeRes = {
cookie: sinon.spy(),
status: sinon.spy(),
json: sinon.spy()
}
fakeNext = sinon.stub();
await proxy.loginRoute(fakeReq, fakeReq, fakeNext).then((_result) => {
result = _result;
});
console.log("result")
console.log(result) // undefined
console.log("result")
});
it("login route test if the stubs are called", async () => {
expect(authService.findByEmail).to.have.been.called // never called
// expect(bcryptStubbing).to.have.been.called // never called
// expect(response.status).to.deep.equal(200); // doesn't work
}).timeout(10000);
after(() => {
sinon.reset()
});
});
Where am i going wrong here in the test?

How can I test the function called inside another function in Nestjs?

i am writing test functions in nestjs and i am new to this task.
I mostly had problems with typeorm. but my current problem is that I do not call the paginate function in the PaginateLib class inside the function I wrote in the service. I tested the userList function directly before, but it gave paginate undefined error. Now I used mock and paginate function in test. it still gives undefined error.
Here's my admin.service code
public async userList(page, limit): Promise<any> {
const opt = {
relations: ['userInfo'],
};
const userData = await this.paginateLib.paginate(
getRepository(Users),
opt,
page,
limit,
);
return userData;
}
Here's Paginate function code in PaginateLib class. I'm cutting this short as I don't think it's very necessary.
export class PaginateLib {
async paginate(repo, opt, page, limit) {
try {
page = Number(page);
limit = Number(limit);
const items = (Number(page) - 1) * Number(limit);
const [data, count] = await repo.findAndCount({
...opt,
skip: Number(items),
take: Number(limit),
});
if (count <= items) {
return [];
}
and here's my test code
class PaginateMock {
paginate(repo: any, opt: any, page: number, limit: number) {
return [];
}
}
describe('AdminService', () => {
let service: AdminService;
let connection: Connection;
let module: TestingModule;
let services: PaginateLib;
beforeAll(async () => {
const ApiServiceProvider = {
provide: PaginateLib,
useClass: PaginateMock,
},
module = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: '****',
host: '****',
port: ****,
username: '****',
password: '****',
database: '****',
entities: [__dirname + '/../../**/*.entity.ts'],
synchronize: true,
}),
],
providers: [
AdminService,
ApiServiceProvider,
],
}).compile();
service = module.get<AdminService>(AdminService);
services = module.get<PaginateLib>(PaginateLib);
});
// afterAll(async () => {
// await module.close();
// });
describe('User Info', () => {
it('should be get user list', async () => {
const paginateSpy = jest.spyOn(services, 'paginate');
expect(paginateSpy).toHaveBeenCalled();
expect(true).toBe(service.userList(1, 1));
});
});
});
I tried different things many times. but the error I get is undefined. what should I do? Is there anyone have an idea?thank you
Try this:
describe('User Info', () => {
it('should be get user list', async () => {
const paginateSpy = jest.spyOn(services, 'paginate');
const userData = await service.userList(1, 1);
expect(paginateSpy).toHaveBeenCalled();
expect(userData).toBe(); // Don't know what userData actually looks like. So this is up to you
});
});

Mock Injectable model in nestjs with Jest

I want to unit test my service. Inside my service I have a constructor that is:
contractService.ts:
export class ContractService {
private logger = new Logger("ContractService");
constructor(
#InjectModel(Contract)
private contractModel: typeof Contract
) {}
async getContracts(query: PaginationInterface): Promise<FetchContract> {
const { limit, page, skip } = paginationParseParams(query);
const { sortBy, direction } = sortParseParams(query, ColumnDetails);
const { count, rows } = await this.contractModel.findAndCountAll({
where: {},
offset: skip,
limit: limit,
order: [[sortBy, direction]],
});
const pages = Math.ceil(count / limit);
const meta = {
limit,
skip,
page,
count,
pages,
sortBy,
direction,
};
return { meta, data: rows };
}
}
My model looks like this: (Model is a class from sequelize-typescript)
export class Contract extends Model<Contract> {
....
}
So I want to create my unit test with jest. When I try to mock the contractModel, it does not find the method, eventhough I am trying to mock it.
const mockContractModel = () => ({
findAndCountAll: jest.fn(),
});
describe("ContractService", () => {
let contractService: ContractService;
let contractModel: Contract;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ContractService,
{
provide: Contract,
useFactory: mockContractModel,
},
],
}).compile();
contractService = module.get<ContractService>(ContractService);
contractModel = module.get<Contract>(Contract);
});
it("should be defined", () => {
expect(contractService).toBeDefined();
});
describe("Get contracts", () => {
it("Should return all the contracts", async () => {
expect(contractModel.findAndCountAll).not.toHaveBeenCalled();
await contractService.getContracts(defaultPagination);
expect(contractModel.findAndCountAll).toHaveBeenCalled();
});
});
});
What is the right way to mock this contractModel?
Instead of using
{
provide: Contract,
useFactory: mockContractModel
}
You should be using
{
provide: getModelToken(Contract),
useFactory: mockContractModel
}
where getModelToken is imported from #nestjs/mongoose. This will get the correct DI token for Nest to know what you're mocking. For more examples, check this git repo

Controller integration testing with nestJS using different guards

I am trying to develop an application using NestJs as the backend framework. Currently I am writing some integration tests for the controllers.
This is my first project using typescript, I usually use Java/Spring but I wanted to learn and give nestJs a try.
I use different guards to access rest endpoints. In this case I have an AuthGuard and RolesGuard
To make the rest endpoint work I just add something like this in the TestingModuleBuilder:
.overrideGuard(AuthGuard())
.useValue({ canActivate: () => true })
The point is, is it possible to define or override this guards for each test to check that the request should fail if no guard or not allowed guard is defined?
My code for the test is the following one:
describe('AuthController integration tests', () => {
let userRepository: Repository<User>
let roleRepository: Repository<Role>
let app: INestApplication
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [
AuthModule,
TypeOrmModule.forRoot(typeOrmConfigTest),
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: jwtConfig.secret,
signOptions: {
expiresIn: jwtConfig.expiresIn
}
})
]
})
.overrideGuard(AuthGuard())
.useValue({ canActivate: () => true })
.overrideGuard(RolesGuard)
.useValue({ canActivate: () => true })
.compile()
app = module.createNestApplication()
await app.init()
userRepository = module.get('UserRepository')
roleRepository = module.get('RoleRepository')
const initializeDb = async () => {
const roles = roleRepository.create([
{ name: RoleName.ADMIN },
{ name: RoleName.TEACHER },
{ name: RoleName.STUDENT }
])
await roleRepository.save(roles)
}
await initializeDb()
})
afterAll(async () => {
await roleRepository.query(`DELETE FROM roles;`)
await app.close()
})
afterEach(async () => {
await userRepository.query(`DELETE FROM users;`)
})
describe('users/roles (GET)', () => {
it('should retrieve all available roles', async () => {
const { body } = await request(app.getHttpServer())
.get('/users/roles')
.set('accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
expect(body).toEqual(
expect.arrayContaining([
{
id: expect.any(String),
name: RoleName.STUDENT
},
{
id: expect.any(String),
name: RoleName.TEACHER
},
{
id: expect.any(String),
name: RoleName.ADMIN
}
])
)
})
})
It's not immediately possibly with the current implementation, but if you save the guard mock as a jest mock it should be possible. Something like this
describe('Controller Integration Testing', () => {
let app: INestApplication;
const canActivate = jest.fn(() => true);
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
})
.overrideGuard(TestGuard)
.useValue({ canActivate })
.compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
it('/ (GET) Fail guard', () => {
canActivate.mockReturnValueOnce(false);
return request(app.getHttpServer())
.get('/')
.expect(403);
});
});

Test NestJS Service against Actual Database

I would like to be able to test my Nest service against an actual database. I understand that most unit tests should use a mock object, but it also, at times, makes sense to test against the database itself.
I have searched through SO and the GH issues for Nest, and am starting to reach the transitive closure of all answers. :-)
I am trying to work from https://github.com/nestjs/nest/issues/363#issuecomment-360105413. Following is my Unit test, which uses a custom provider to pass the repository to my service class.
describe("DepartmentService", () => {
const token = getRepositoryToken(Department);
let service: DepartmentService;
let repo: Repository<Department>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
DepartmentService,
{
provide: token,
useClass: Repository
}
]
}).compile();
service = module.get<DepartmentService>(DepartmentService);
repo = module.get(token);
});
Everything compiles properly, TypeScript seems happy. However, when I try to execute create or save on my Repository instance, the underlying Repository appears to be undefined. Here's the stack backtrace:
TypeError: Cannot read property 'create' of undefined
at Repository.Object.<anonymous>.Repository.create (repository/Repository.ts:99:29)
at DepartmentService.<anonymous> (relational/department/department.service.ts:46:53)
at relational/department/department.service.ts:19:71
at Object.<anonymous>.__awaiter (relational/department/department.service.ts:15:12)
at DepartmentService.addDepartment (relational/department/department.service.ts:56:16)
at Object.<anonymous> (relational/department/test/department.service.spec.ts:46:35)
at relational/department/test/department.service.spec.ts:7:71
It appears that the EntityManager instance with the TypeORM Repository class is not being initialized; it is the undefined reference that this backtrace is complaining about.
How do I get the Repository and EntityManager to initialize properly?
thanks,
tom.
To initialize typeorm properly, you should just be able to import the TypeOrmModule in your test:
Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
// ...
}),
TypeOrmModule.forFeature([Department])
]
I prefer not using #nestjs/testing for the sake of simplicity.
First of all, create a reusable helper:
/* src/utils/testing-helpers/createMemDB.js */
import { createConnection, EntitySchema } from 'typeorm'
type Entity = Function | string | EntitySchema<any>
export async function createMemDB(entities: Entity[]) {
return createConnection({
// name, // let TypeORM manage the connections
type: 'sqlite',
database: ':memory:',
entities,
dropSchema: true,
synchronize: true,
logging: false
})
}
Then, write test:
/* src/user/user.service.spec.ts */
import { Connection, Repository } from 'typeorm'
import { createMemDB } from '../utils/testing-helpers/createMemDB'
import UserService from './user.service'
import User from './user.entity'
describe('User Service', () => {
let db: Connection
let userService: UserService
let userRepository: Repository<User>
beforeAll(async () => {
db = await createMemDB([User])
userRepository = await db.getRepository(User)
userService = new UserService(userRepository) // <--- manually inject
})
afterAll(() => db.close())
it('should create a new user', async () => {
const username = 'HelloWorld'
const password = 'password'
const newUser = await userService.createUser({ username, password })
expect(newUser.id).toBeDefined()
const newUserInDB = await userRepository.findOne(newUser.id)
expect(newUserInDB.username).toBe(username)
})
})
Refer to https://github.com/typeorm/typeorm/issues/1267#issuecomment-483775861
Here's an update to the test that employs Kim Kern's suggestion.
describe("DepartmentService", () => {
let service: DepartmentService;
let repo: Repository<Department>;
let module: TestingModule;
beforeAll(async () => {
module = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot(),
TypeOrmModule.forFeature([Department])
],
providers: [DepartmentService]
}).compile();
service = module.get<DepartmentService>(DepartmentService);
repo = module.get<Repository<Department>>(getRepositoryToken(Department));
});
afterAll(async () => {
module.close();
});
it("should be defined", () => {
expect(service).toBeDefined();
});
// ...
}
I created a test orm configuration
// ../test/db.ts
import { TypeOrmModuleOptions } from '#nestjs/typeorm';
import { EntitySchema } from 'typeorm';
type Entity = Function | string | EntitySchema<any>;
export const createTestConfiguration = (
entities: Entity[],
): TypeOrmModuleOptions => ({
type: 'sqlite',
database: ':memory:',
entities,
dropSchema: true,
synchronize: true,
logging: false,
});
which I then utilize when setting up the tests
// books.service.test.ts
import { Test, TestingModule } from '#nestjs/testing';
import { HttpModule, HttpService } from '#nestjs/common';
import { TypeOrmModule, getRepositoryToken } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { BooksService } from './books.service';
import { Book } from './book.entity';
import { createTestConfiguration } from '../../test/db';
describe('BooksService', () => {
let module: TestingModule;
let service: BooksService;
let httpService: HttpService;
let repository: Repository<Book>;
beforeAll(async () => {
module = await Test.createTestingModule({
imports: [
HttpModule,
TypeOrmModule.forRoot(createTestConfiguration([Book])),
TypeOrmModule.forFeature([Book]),
],
providers: [BooksService],
}).compile();
httpService = module.get<HttpService>(HttpService);
service = module.get<BooksService>(BooksService);
repository = module.get<Repository<Book>>(getRepositoryToken(Book));
});
afterAll(() => {
module.close();
});
it('should be defined', () => {
expect(service).toBeDefined();
});
This allows to query the repository after the tests and ensure that the correct data was inserted.
I usually import AppModule for database connection, and finally after tests are executed I close the connection:
let service: SampleService;
let connection: Connection;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [AppModule, TypeOrmModule.forFeature([SampleEntity])],
providers: [SampleService],
}).compile();
service = module.get<SampleService>(SampleService);
connection = await module.get(getConnectionToken());
});
afterEach(async () => {
await connection.close();
});
I used existing AppModule for testing:
import { INestApplication } from '#nestjs/common';
import { NestFactory } from '#nestjs/core';
import { AppModule } from '../../../app.module';
import { AuthService } from '../auth.service';
describe('AuthService', () => {
let app: INestApplication;
let service: AuthService;
beforeAll(async () => {
app = await NestFactory.create(AppModule);
service = app.get(AuthService);
});
afterAll(async () => {
await app.close();
});
it('AuthService should be defined', () => {
expect(service).toBeDefined();
});
describe('login', () => {
it('should login user', async () => {
const user = await service.login({ email: 'xxxzei#mail.ru', password: '12345678' });
expect(user.id).toBeDefined();
});
});
});
Also to add env variables in your configuration file or AppModule:
import { config as testConfig } from 'dotenv';
if (process.env.NODE_ENV === 'test') {
testConfig({ path: resolve('./.env') });
}

Categories

Resources