/
testing-module.builder.ts
104 lines (88 loc) 路 3.34 KB
/
testing-module.builder.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { Logger, Module } from '@nestjs/common';
import { ModuleMetadata } from '@nestjs/common/interfaces';
import { ApplicationConfig } from '@nestjs/core/application-config';
import { NestContainer } from '@nestjs/core/injector/container';
import { InstanceLoader } from '@nestjs/core/injector/instance-loader';
import { MetadataScanner } from '@nestjs/core/metadata-scanner';
import { DependenciesScanner } from '@nestjs/core/scanner';
import { OverrideBy, OverrideByFactoryOptions } from './interfaces';
import { TestingLogger } from './services/testing-logger.service';
import { TestingModule } from './testing-module';
export class TestingModuleBuilder {
private readonly applicationConfig = new ApplicationConfig();
private readonly container = new NestContainer(this.applicationConfig);
private readonly overloadsMap = new Map();
private readonly scanner: DependenciesScanner;
private readonly instanceLoader = new InstanceLoader(this.container);
private readonly module: any;
constructor(metadataScanner: MetadataScanner, metadata: ModuleMetadata) {
this.scanner = new DependenciesScanner(
this.container,
metadataScanner,
this.applicationConfig,
);
this.module = this.createModule(metadata);
}
public overridePipe<T = any>(typeOrToken: T): OverrideBy {
return this.override(typeOrToken, false);
}
public overrideFilter<T = any>(typeOrToken: T): OverrideBy {
return this.override(typeOrToken, false);
}
public overrideGuard<T = any>(typeOrToken: T): OverrideBy {
return this.override(typeOrToken, false);
}
public overrideInterceptor<T = any>(typeOrToken: T): OverrideBy {
return this.override(typeOrToken, false);
}
public overrideProvider<T = any>(typeOrToken: T): OverrideBy {
return this.override(typeOrToken, true);
}
public async compile(): Promise<TestingModule> {
this.applyLogger();
await this.scanner.scan(this.module);
this.applyOverloadsMap();
await this.instanceLoader.createInstancesOfDependencies();
this.scanner.applyApplicationProviders();
const root = this.getRootModule();
return new TestingModule(this.container, [], root, this.applicationConfig);
}
private override<T = any>(typeOrToken: T, isProvider: boolean): OverrideBy {
const addOverload = (options: any) => {
this.overloadsMap.set(typeOrToken, {
...options,
isProvider,
});
return this;
};
return this.createOverrideByBuilder(addOverload);
}
private createOverrideByBuilder(
add: (provider: any) => TestingModuleBuilder,
): OverrideBy {
return {
useValue: value => add({ useValue: value }),
useFactory: (options: OverrideByFactoryOptions) =>
add({ ...options, useFactory: options.factory }),
useClass: metatype => add({ useClass: metatype }),
};
}
private applyOverloadsMap() {
[...this.overloadsMap.entries()].forEach(([item, options]) => {
this.container.replace(item, options);
});
}
private getRootModule() {
const modules = this.container.getModules().values();
return modules.next().value;
}
private createModule(metadata: ModuleMetadata) {
// tslint:disable-next-line:class-name
class _RootTestModule {}
Module(metadata)(_RootTestModule);
return _RootTestModule;
}
private applyLogger() {
Logger.overrideLogger(new TestingLogger());
}
}