Nest can't resolve dependencies in the RootTestModule context when I use Bazel Test - jestjs

I need to run my tests in the bezel. how can I solve this mysterious problem?
I have a nestjs project contains multiple apps and libs. When I run the test yarn jest --config ./jest.config.json libs/lib1, it works perfectly. However when I run with bezel bazel test //libs/lib1/... it gives me an error "Nest can't resolve dependencies ... Please make sure that the argument dependency at index ... is available in the RootTestModule context.".
REPO
https://github.com/smhmayboudi/bazel_jest_nestjs
I find out that the order of mapping at jest.config.json is important.
this one works well ( shows test + coverage ), but dependency problem
"moduleNameMapper": {
"#melo/lib1": "<rootDir>/libs/lib1/src",
"#melo/lib1/(.*)": "<rootDir>/libs/lib1/src/$1",
},
this one works ( show just pass message with out actual test result and coverage !? )
"moduleNameMapper": {
"#melo/lib1/(.*)": "<rootDir>/libs/lib1/src/$1",
"#melo/lib1": "<rootDir>/libs/lib1/src",
},
Jest Config
{
"coverageReporters": ["lcov", "text-summary"],
"moduleNameMapper": {
"#melo/libs1": "<rootDir>/libs/libs1/src",
"#melo/libs1/(.*)": "<rootDir>/libs/libs1/src/$1",
},
"modulePathIgnorePatterns": ["/bazel-out/", "/node_modules/"],
"preset": "ts-jest",
"testEnvironment": "node"
}
Bazel Config
ts_library(
name = "lib1_test_ts_library",
srcs = glob(["*spec.ts"]),
runtime = "nodejs",
deps = [
":lib1_ts_library",
"#npm//#nestjs/common",
"#npm//#nestjs/testing",
"#npm//#types/jest",
"#npm//rxjs",
"#npm//ts-jest",
],
)
jest_test(
name = "lib1_jest_test",
srcs = glob(["*spec.ts"]),
jest_config = "//:jest.config.json",
deps = [
":lib1_test_ts_library",
],
coverage = True,
)
Error Log
INFO: Invocation ID: 84f45d55-c6e4-4c2a-b05d-367d0f84baf7
INFO: Analyzed target //libs/lib1/src:lib1_jest_test (633 packages loaded, 19569 targets configured).
INFO: Found 1 test target...
WARNING: failed to create one or more convenience symlinks for prefix 'dist/':
cannot create symbolic link bazel-out -> /Users/WHOAMI/Developer/MY_PROJECT/bazel-out/execroot/melo/bazel-out: /Users/WHOAMI/Developer/MY_PROJECT/bazel-out (File exists)
FAIL: //libs/lib1/src:lib1_jest_test (see /Users/WHOAMI/Developer/MY_PROJECT/bazel-out/execroot/melo/bazel-out/darwin-fastbuild/testlogs/libs/lib1/src/lib1_jest_test/test.log)
INFO: From Testing //libs/lib1/src:lib1_jest_test:
==================== Test output for //libs/lib1/src:lib1_jest_test:
PASS libs/lib1/src/lib1.util.spec.ts (23.866 s)
PASS libs/lib1/src/lib1.interceptor.spec.ts (23.977 s)
FAIL libs/lib1/src/lib1.service.spec.ts (24.717 s)
● ApmService › should be defined
Nest can't resolve dependencies of the ApmService (?). Please make sure that the argument dependency at index [0] is available in the RootTestModule context.
Potential solutions:
- If dependency is a provider, is it part of the current RootTestModule?
- If dependency is exported from a separate #Module, is that module imported within RootTestModule?
#Module({
imports: [ /* the Module containing dependency */ ]
})
at Injector.resolveSingleParam (../../../../../../../../node_modules/#nestjs/core/injector/injector.js:134:19)
at resolveParam (../../../../../../../../node_modules/#nestjs/core/injector/injector.js:102:49)
at Array.map (<anonymous>)
at Injector.resolveConstructorParams (../../../../../../../../node_modules/#nestjs/core/injector/injector.js:117:58)
at Injector.loadInstance (../../../../../../../../node_modules/#nestjs/core/injector/injector.js:81:20)
at Injector.loadProvider (../../../../../../../../node_modules/#nestjs/core/injector/injector.js:38:20)
at ../../../../../../../../node_modules/#nestjs/core/injector/instance-loader.js:43:62
at Array.map (<anonymous>)
at InstanceLoader.createInstancesOfProviders (../../../../../../../../node_modules/#nestjs/core/injector/instance-loader.js:43:36)
at ../../../../../../../../node_modules/#nestjs/core/injector/instance-loader.js:28:24
● ApmService › should be defined
expect(received).toBeDefined()
Received: undefined
56 |
57 | it("should be defined", () => {
> 58 | expect(service).toBeDefined();
| ^
59 | });
60 |
61 | it("start should be called", () => {
at Object.<anonymous> (libs/lib1/src/lib1.service.spec.ts:58:21)
...
Test Suites: 2 failed, 2 passed, 4 total
Tests: 27 failed, 3 todo, 6 passed, 36 total
Snapshots: 0 total
Time: 26.102 s
Ran all test suites within paths "libs/lib1/src/lib1.decorator.spec.ts", "libs/lib1/src/lib1.interceptor.spec.ts", "libs/lib1/src/lib1.service.spec.ts", "libs/lib1/src/lib1.util.spec.ts".
================================================================================
Target //libs/lib1/src:lib1_jest_test up-to-date:
dist/bin/libs/lib1/src/lib1_jest_test.sh
dist/bin/libs/lib1/src/lib1_jest_test_loader.js
dist/bin/libs/lib1/src/lib1_jest_test_require_patch.js
INFO: Elapsed time: 83.878s, Critical Path: 59.53s
INFO: 4 processes: 4 local.
INFO: Build completed, 1 test FAILED, 12 total actions
//libs/lib1/src:lib1_jest_test FAILED in 28.2s
/Users/WHOAMI/Developer/MY_PROJECT/bazel-out/execroot/melo/bazel-out/darwin-fastbuild/testlogs/libs/lib1/src/lib1_jest_test/test.log
INFO: Build completed, 1 test FAILED, 12 total actions

Add providers to your RootTestModule. Nest doesn't automatically include the services in your test, depending on if you used the cli vs creating the files/folders directly.
const module: TestingModule = await Test.createTestingModule({
providers: [/** Services goes here **/],
controllers: [CustomersController],
}).compile();
Not working vs Working below
import { Test, TestingModule } from '#nestjs/testing';
import { CustomersController } from './customers.controller';
describe('CustomersController', () => {
let controller: CustomersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CustomersController],
}).compile();
controller = module.get<CustomersController>(CustomersController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
it('shoud return customer', async () => {
const tcase = await controller.d({});
expect(tcase).toHaveProperty('firstName');
})
});
Working (I had the exact error message with different filenames ofcourse)
import { Test, TestingModule } from '#nestjs/testing';
import { CustomersController } from './customers.controller';
import { CustomersService } from './customers.service';
describe('CustomersController', () => {
let controller: CustomersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [CustomersService],
controllers: [CustomersController],
}).compile();
controller = module.get<CustomersController>(CustomersController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
it('shoud return customer', async () => {
const tcase = await controller.d({});
expect(tcase).toHaveProperty('firstName');
})
});

A potential workaround is to declare "empty"
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [{
provide: CustomerService,
useValue: {},
}],
controllers: [CustomersController],
}).compile();

The solution that worked for me was following the unit test examples of the library.
import { Test, TestingModule } from '#nestjs/testing';
import { CreateUserDto } from './dto/create-user.dto';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
const createUserDto: CreateUserDto = {
firstName: 'firstName #1',
lastName: 'lastName #1',
};
describe('UsersController', () => {
let usersController: UsersController;
let usersService: UsersService;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
providers: [ // <---------- THIS IS THE MOST IMPORTANT SECTION TO SOLVE THIS ISSUE.
{
provide: UsersService,
useValue: {
create: jest
.fn()
.mockImplementation((user: CreateUserDto) =>
Promise.resolve({ id: '1', ...user }),
),
findAll: jest.fn().mockResolvedValue([
{
firstName: 'firstName #1',
lastName: 'lastName #1',
},
{
firstName: 'firstName #2',
lastName: 'lastName #2',
},
]),
findOne: jest.fn().mockImplementation((id: string) =>
Promise.resolve({
firstName: 'firstName #1',
lastName: 'lastName #1',
id,
}),
),
remove: jest.fn(),
},
},
],
}).compile();
usersController = app.get<UsersController>(UsersController);
usersService = app.get<UsersService>(UsersService);
});
it('should be defined', () => {
expect(usersController).toBeDefined();
});
describe('create()', () => {
it('should create a user', () => {
expect(usersController.create(createUserDto)).resolves.toEqual({
id: '1',
...createUserDto,
});
expect(usersService.create).toHaveBeenCalled();
expect(usersService.create).toHaveBeenCalledWith(createUserDto);
});
});
describe('findAll()', () => {
it('should find all users ', () => {
usersController.findAll();
expect(usersService.findAll).toHaveBeenCalled();
});
});
describe('findOne()', () => {
it('should find a user', () => {
usersController.findOne('1');
expect(usersService.findOne).toHaveBeenCalled();
expect(usersController.findOne('1')).resolves.toEqual({
firstName: 'firstName #1',
lastName: 'lastName #1',
id: '1',
});
});
});
describe('remove()', () => {
it('should remove the user', () => {
usersController.remove('2');
expect(usersService.remove).toHaveBeenCalled();
});
});
});
The key change was to update the 'providers' property to use an object instead of just using: providers: [CustomersService],.

Related

Nest can't resolve dependencies of the UsersService (?). Please make sure that the argument UserRepositor

Nest can't resolve dependencies of the UsersService (?). 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
I'm currently workin in v9 and I have this error, I don't understand why.
Here is my repo: https://github.com/ociel-gonzalez-solis/cv-nestjs-test-portafolio
You never provide a custom provider to mock the UserRepository. Something like
import { Test, TestingModule } from '#nestjs/testing';
import { UsersService } from './users.service';
describe('UsersService', () => {
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: getRepositoryToken(User),
useValue: {
create: jest.fn(),
save: jest.fn(),
find: jest.fn(),
}
},
],
}).compile();
service = module.get<UsersService>(UsersService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
You can then tailor the jest.fn() methods to your liking as your test needs. You can find a whole repository of test examples here

e2e test failing - getRepository is null

When I run the e2e test(as integration tests) I get a getRepository null error. I import the entire app module in my test spec file(below),the error occurs, which says something like this:
[Nest] 47867 - 08/22/2022, 8:07:35 PM ERROR [ExceptionsHandler] Cannot read property 'getRepository' of null
TypeError: Cannot read property 'getRepository' of null
TypeError: Cannot read property 'getRepository' of null
at new usersService (/mypath/src/users/users.service.ts:35:42)
at Injector.instantiateClass (/mypath/node_modules/#nestjs/core/injector/injector.js:330:19)
at callback (/mypath/node_modules/#nestjs/core/injector/injector.js:48:41)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at Injector.loadInstance (/mypath/node_modules/#nestjs/core/injector/injector.js:52:9)
at Injector.loadProvider (/mypath/node_modules/#nestjs/core/injector/injector.js:74:9)
at Injector.resolveComponentHost (/mypath/node_modules/#nestjs/core/injector/injector.js:192:13)
at async Promise.all (index 0)
at Injector.loadCtorMetadata (/mypath/node_modules/#nestjs/core/injector/injector.js:358:23)
at Injector.resolveConstructorParams (/mypath/node_modules/#nestjs/core/injector/injector.js:89:26)
FAIL test/user.service.int-spec.ts (10.525 s)
GET /users
✓ (GET) / (102 ms)
✕ (GET) /users (62 ms)
● GET /users › (GET) /users
expected 200 "OK", got 500 "Internal Server Error"
26 |
27 | it('(GET) /users', () => {
> 28 | return request(app.getHttpServer()).get('/users').expect(200);
| ^
29 | });
30 | });
31 |
at Object.<anonymous> (test/user.service.int-spec.ts:28:59)
----
at Test._assertStatus (node_modules/supertest/lib/test.js:252:14)
at node_modules/supertest/lib/test.js:306:17
at Test._assertFunction (node_modules/supertest/lib/test.js:285:13)
at Test.assert (node_modules/supertest/lib/test.js:164:23)
at Server.localAssert (node_modules/supertest/lib/test.js:120:14)
The folder structure is this:
parent_folder
| package.json
| package-lock.json
| ---src
| \-User
| \-user.module.ts
| \-user.service.ts
| \-user.controller.ts
|...
| ---tests
| \-jest-int.json
| \-user.int-spec.ts
The jest config file contains this:
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": "../", // <<<--- I use absolute path path, so rootDir is "../"
"roots": ["<rootDir>"],
"modulePaths": ["<rootDir>"],
"moduleDirectories": ["node_modules"],
"testEnvironment": "node",
"testRegex": ".int-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}
The module contains this only:
import { Module } from '#nestjs/common';
import { UsersController } from './Users.controller';
import { UsersService } from './Users.service';
#Module({
providers: [UsersService],
controllers: [UsersController],
})
export class UserModule {}
The service contains:
#Injectable()
export class UsersService {
private userRepository: Repository<User>;
private fileRepository: Repository<file>;
private filedworthRepository: Repository<filedworth>;
private filedValueRepository: Repository<filedValue>;
private fileStrategyRepository: Repository<fileStrategy>;
private valueRepository: Repository<Value>;
private defaultData = {
created_date: new Date(),
updated_date: new Date(),
created_by: 'user',
updated_by: 'user',
};
constructor(#Inject(CONNECTION) private connection: DataSource) {
this.userRepository = connection.getRepository(user);
this.fileRepository = connection.getRepository(file);
this.filedworthRepository =
connection.getRepository(filedworth);
this.filedValueRepository =
connection.getRepository(filedValue);
this.fileStrategyRepository =
connection.getRepository(fileStrategy);
this.ValueRepository = connection.getRepository(Value);
}
...//other methods
}
The controller is:
#Controller('users')
export class usersController {
constructor(private usersService: usersService) {}
#Get()
getusers(
#Query()
query: GetUsersFilterDto,
) {
return this.usersService.getusers(query);
}
...//others
}
and the test file itself contains the following:
import { Test, TestingModule } from '#nestjs/testing';
import { INestApplication } from '#nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('GET /users ', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it('(GET) /', () => {
return request(app.getHttpServer()).get('/').expect(200);
});
it('(GET) /users', () => {
return request(app.getHttpServer()).get('/users').expect(200);
});
});
I run the test using:
npm run test:int // "test:int": "jest -i --no-cache --detectOpenHandles --config ./test/jest-int.json"
Is there something I'm missing? Hopefully these are enough details to convey my issue.
You need to add CONNECTION as a provider to your test app: TestingModule =
await Test.createTestingModule({
imports: [AppModule],
providers: [
{ provide: CONNECTION, getRepository: jest.fn() },
],
}).compile();
What Georgi has mentioned was true, I hadn't provided the values of the dependency CONNECTION that was being injected. But, the syntax mentioned there didn't work, this did:
beforeAll(async () => {
const connection = await DataSource(myDB_Config);//hosturl, port etc.
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
})
.overrideProvider(CONNECTION)
.useValue(connection)
.compile();
app = moduleFixture.createNestApplication();
await app.init();
});

Jest .toHaveBeenCalled() not recording function calls

I'm testing a service in my NestJs application which calls a factory to receive an object with a method up(), which I'm mocking like this:
export const mockExecutorFactory = {
getExecutor: jest.fn().mockImplementation(() => {
return {
up: jest.fn().mockImplementation((_updatedInstance, _parameters) => {
console.log('****************************');
return Promise.resolve({ successful: true });
}),
};
}),
};
In my describe block for the service test I initialize the executor like this:
let executor;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
InstanceService,
{ provide: getRepositoryToken(Instance), useValue: mockInstanceRepository },
ExecutorFactory,
],
})
.overrideProvider(ExecutorFactory)
.useValue(mockExecutorFactory)
.compile();
service = module.get<InstanceService>(InstanceService);
executor = module.get<ExecutorFactory>(ExecutorFactory).getExecutor();
});
And the test its self is written like this:
it('should create a new instance with default settings', async () => {
// Check if instance created correctly
expect(
await service.createInstance(
MOCK_INSTANCE_CREATE_PARAMS.solutionId,
MOCK_INSTANCE_CREATE_PARAMS.instanceType,
MOCK_INSTANCE_CREATE_PARAMS.orgId,
MOCK_INSTANCE_CREATE_PARAMS.parameters,
MOCK_INSTANCE_CREATE_PARAMS.customPrice,
true,
MOCK_INSTANCE_CREATE_PARAMS.req,
),
).toEqual({ instance: MOCK_INSTANCE_DEFAULT });
console.log(executor);
expect(executor.up).toHaveBeenCalled();
});
Essentially, the createInstance() runs through some logic and at the end is supposed to call the executor's up() function.
From the terminal output (photo below) I can see by the console logs that the the up() is being called, but the test fails... Any idea why?

Nest can't resolve dependencies: NettJS Unit testing with TypeORM

i have following error when try to Unit testing with NestJS.
Nest can't resolve dependencies of the UsersService (UsersRepository, ?, UserRoleRepository, RoleRepository, JWTService). Please make sure that the argument CredentialsRepository at index [1] is available in the RootTestModule context.
test code
describe("UsersService", () => {
let service: UsersService;
let repositoryMock: MockType<Repository<Users>>;
let model: typeof Users;
let repo: Repository<Users>;
let userController: UsersController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: "mysql",
host: config.db.host,
port: config.db.port,
username: config.db.username,
password: config.db.password,
database: config.db.database,
autoLoadEntities: true,
synchronize: true,
}),
CredentialsModule,
],
providers: [
UsersService,
CredentialsService,
AuthService,
JWTService,
{
provide: getRepositoryToken(Users),
// useValue: {
// find: jest.fn(() => [Alluser]),
// },
useFactory: repositoryMockFactory,
},
],
}).compile();
service = module.get<UsersService>(UsersService);
repositoryMock = module.get(getRepositoryToken(Users));
});
it("User details get by Id", async () => {
repositoryMock.findOne.mockReturnValue(testUser);
expect(service.findUser(testUser.id)).toEqual(testUser);
expect(repositoryMock.findOne).toHaveBeenCalledWith(testUser.id);
// expect(await service.findOne(1)).toBeCalledWith(testUser);
});
// it("All Users details ", async () => {
// expect(await service.find()).toEqual([Alluser]);
// });
// it('Create new User ', async () => {
// expect(await service.createNewUser(createUser)).toEqual(testUser);
// });
});
As per the code, it seems that you are trying to test "UserService", But in the test module, you also have "CredentialsService" which is dependent on the "CredentialsRepository", and is not mocked.
providers: [
UsersService,
CredentialsService,
AuthService,
JWTService,
{
provide: getRepositoryToken(Users),
// useValue: {
// find: jest.fn(() => [Alluser]),
// },
useFactory: repositoryMockFactory,
},
],
The basic idea of unit testing is to test one block of the code, and mock the other dependencies of the code, which in this case are "CredentialsService, AuthService, and JWTService".
If the dependencies of the code will not be mocked then the real dependent code will be executed, which will call the further dependencies of the dependent code.
So to avoid those situations, you should mock "CredentialsService, AuthService, and JWTService" services as well, the way you have done for the user service, and then the reported error will be gone.
Firstly declare the variables
let credentialService: CredentialsService;
let authService: AuthService;
let jwtService: JWTService;
And then in the beforeEach block initialize those dependent services
service = module.get<UsersService>(UsersService)
credentialService = module.get<CredentialsService>(CredentialsService)
authService = module.get<AuthService>(AuthService)
jwtService = module.get<JWTService>(JWTService)

Jest with NestJS and async function

I'm trying to a test a async function of a service in nestJS.
this function is async... basically get a value (JSON) from database (using repository - TypeORM), and when successfully get the data, "transform" to a different class (DTO)...
the implementation:
async getAppConfig(): Promise<ConfigAppDto> {
return this.configRepository.findOne({
key: Equal("APPLICATION"),
}).then(config => {
if (config == null) {
return new class implements ConfigAppDto {
clientId = '';
clientSecret = '';
};
}
return JSON.parse(config.value) as ConfigAppDto;
});
}
using a controller, I checked that this worked ok.
Now, I'm trying to use Jest to do the tests, but with no success...
My problem is how to mock the findOne function from repository..
Edit: I'm trying to use #golevelup/nestjs-testing to mock Repository!
I already mocked the repository, but for some reason, the resolve is never called..
describe('getAppConfig', () => {
const repo = createMock<Repository<Config>>();
beforeEach(async () => {
await Test.createTestingModule({
providers: [
ConfigService,
{
provide: getRepositoryToken(Config),
useValue: repo,
}
],
}).compile();
});
it('should return ConfigApp parameters', async () => {
const mockedConfig = new Config('APPLICATION', '{"clientId": "foo","clientSecret": "bar"}');
repo.findOne.mockResolvedValue(mockedConfig);
expect(await repo.findOne()).toEqual(mockedConfig); // ok
const expectedReturn = new class implements ConfigAppDto {
clientId = 'foo';
clientSecret = 'bar';
};
expect(await service.getAppConfig()).toEqual(expectedReturn);
// jest documentation about async -> https://jestjs.io/docs/en/asynchronous
// return expect(service.getAppConfig()).resolves.toBe(expectedReturn);
});
})
the expect(await repo.findOne()).toEqual(mockedConfig); works great;
expect(await service.getAppConfig()).toEqual(expectedReturn); got a timeout => Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout;
using debug, I see that the service.getAppConfig() is called, the repository.findOne() too, but the .then of repository of findOne is never called.
Update: I'm trying to mock the repository using #golevelup/nestjs-testing, and for some reason, the mocked result don't works on service.
If I mock the repository using only jest (like code below), the test works... so, I think my real problem it's #golevelup/nestjs-testing.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
So, my real problem is how I'm mocking the Repository on NestJS.
For some reason, when I mock using the #golevelup/nestjs-testing, weird things happens!
I really don't found a good documentation about this on #golevelup/nestjs-testing, so, I gave up using it.
My solution for the question was to use only Jest and NestJS functions... the result code was:
Service:
// i'm injecting Connection because I need for some transactions later;
constructor(#InjectRepository(Config) private readonly configRepo: Repository<Config>, private connection: Connection) {}
async getAppConfig(): Promise<ConfigApp> {
return this.configRepo.findOne({
key: Equal("APPLICATION"),
}).then(config => {
if (config == null) {
return new ConfigApp();
}
return JSON.parse(config.value) as ConfigApp;
})
}
Test:
describe('getAppConfig', () => {
const configApi = new Config();
configApi.key = 'APPLICATION';
configApi.value = '{"clientId": "foo", "clientSecret": "bar"}';
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
ConfigAppService,
{
provide: getRepositoryToken(Config),
useValue: {
findOne: jest.fn().mockResolvedValue(new
Config("APPLICATION", '{"clientId": "foo", "clientSecret": "bar"}')),
},
},
{
provide: getConnectionToken(),
useValue: {},
}
],
}).compile();
service = module.get<ConfigAppService>(ConfigAppService);
});
it('should return ConfigApp parameters', async () => {
const expectedValue: ConfigApp = new ConfigApp("foo", "bar");
return service.getAppConfig().then(value => {
expect(value).toEqual(expectedValue);
})
});
})
some sources utilized for this solution:
https://github.com/jmcdo29/testing-nestjs/tree/master/apps/typeorm-sample
I think expect(await repo.findOne()).toEqual(mockedConfig); works because you mocked it, so it returns right away.
In the case of expect(await service.getAppConfig()).toEqual(expectedReturn);, you did not mock it so it is probably taking more time, thus the it function returns before the Promise resolved completely.
The comments you posted from jest documentation should do the trick if you mock the call to getAppConfig().
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
or
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))
This answer from #roberto-correia made me wonder if there must be something wrong with the way we are using createMock from the package #golevelup/nestjs-testing.
It turns out that the reason why the method exceeds the execution time has to do with the fact that createMock does not implement the mocking, and does not return anything, unless told to do so.
To make the method work, we have to make the mocked methods resolve something at the beginning of the test:
usersRepository.findOneOrFail.mockResolvedValue({ userId: 1, email: "some-random-email#email.com" });
A basic working solution:
describe("UsersService", () => {
let usersService: UsersService;
const usersRepository = createMock<Repository<User>>();
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: getRepositoryToken(User),
useValue: usersRepository,
},
}).compile();
usersService = module.get(UsersService);
});
it("should be defined", () => {
expect(usersService).toBeDefined();
});
it("finds a user", async () => {
usersRepository.findOne.mockResolvedValue({ userId: 1, email: "some-random-email#email.com" });
expect(await usersRepository.findOne()).toBe({ userId: 1, email: "some-random-email#email.com" });
});
});

Resources