Skip to content

Commit 0abbdbc

Browse files
Merge pull request #15172 from mag123c/15144-fix-missing-strategy-in-usefactory
fix(microservices): support custom strategy in async usefactory config
2 parents 9e24342 + 6f43983 commit 0abbdbc

File tree

2 files changed

+170
-9
lines changed

2 files changed

+170
-9
lines changed

packages/microservices/nest-microservice.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,29 @@ export class NestMicroservice
7878
public createServer(config: CompleteMicroserviceOptions) {
7979
try {
8080
if ('useFactory' in config) {
81-
this.microserviceConfig = this.resolveAsyncOptions(config);
81+
const resolvedConfig = this.resolveAsyncOptions(config);
82+
this.microserviceConfig = resolvedConfig;
83+
84+
// Inject custom strategy
85+
if ('strategy' in resolvedConfig) {
86+
this.serverInstance = resolvedConfig.strategy as Server;
87+
return;
88+
}
8289
} else {
8390
this.microserviceConfig = {
8491
transport: Transport.TCP,
8592
...config,
8693
} as MicroserviceOptions;
87-
}
8894

89-
if ('strategy' in config) {
90-
this.serverInstance = config.strategy as Server;
91-
return;
92-
} else {
93-
this.serverInstance = ServerFactory.create(
94-
this.microserviceConfig,
95-
) as Server;
95+
if ('strategy' in config) {
96+
this.serverInstance = config.strategy as Server;
97+
return;
98+
}
9699
}
100+
101+
this.serverInstance = ServerFactory.create(
102+
this.microserviceConfig,
103+
) as Server;
97104
} catch (e) {
98105
this.logger.error(e);
99106
throw e;
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { NestMicroservice } from '@nestjs/microservices/nest-microservice';
2+
import { Server, ServerTCP } from '@nestjs/microservices/server';
3+
import { GraphInspector } from '@nestjs/core/inspector/graph-inspector';
4+
import { ApplicationConfig } from '@nestjs/core/application-config';
5+
import { Transport } from '@nestjs/microservices/enums';
6+
import { expect } from 'chai';
7+
import * as sinon from 'sinon';
8+
import { AsyncMicroserviceOptions } from '@nestjs/microservices/interfaces';
9+
10+
const createMockGraphInspector = (): GraphInspector =>
11+
({
12+
insertOrphanedEnhancer: sinon.stub(),
13+
}) as unknown as GraphInspector;
14+
15+
const createMockAppConfig = (): ApplicationConfig =>
16+
({
17+
useGlobalFilters: sinon.stub(),
18+
useGlobalPipes: sinon.stub(),
19+
useGlobalGuards: sinon.stub(),
20+
useGlobalInterceptors: sinon.stub(),
21+
setIoAdapter: sinon.stub(),
22+
}) as unknown as ApplicationConfig;
23+
24+
const mockContainer = {
25+
getModuleCompiler: sinon.stub(),
26+
getModules: () => new Map(),
27+
get: () => null,
28+
getHttpAdapterHost: () => undefined,
29+
} as any;
30+
31+
describe('NestMicroservice', () => {
32+
let mockGraphInspector: GraphInspector;
33+
let mockAppConfig: ApplicationConfig;
34+
35+
beforeEach(() => {
36+
mockGraphInspector = createMockGraphInspector();
37+
mockAppConfig = createMockAppConfig();
38+
});
39+
40+
afterEach(() => {
41+
sinon.restore();
42+
});
43+
44+
it('should use ServerFactory if no strategy is provided', () => {
45+
const instance = new NestMicroservice(
46+
mockContainer,
47+
{ transport: Transport.TCP },
48+
mockGraphInspector,
49+
mockAppConfig,
50+
);
51+
52+
expect((instance as any).serverInstance).to.be.instanceOf(ServerTCP);
53+
});
54+
55+
it('should use provided strategy if present in config', () => {
56+
const strategy = new (class extends Server {
57+
listen = sinon.spy();
58+
close = sinon.spy();
59+
on = sinon.stub();
60+
unwrap = sinon.stub();
61+
})();
62+
63+
const instance = new NestMicroservice(
64+
mockContainer,
65+
{ strategy },
66+
mockGraphInspector,
67+
mockAppConfig,
68+
);
69+
70+
expect((instance as any).serverInstance).to.equal(strategy);
71+
});
72+
73+
it('should use strategy resolved from useFactory config', () => {
74+
const strategy = new (class extends Server {
75+
listen = sinon.spy();
76+
close = sinon.spy();
77+
on = sinon.stub();
78+
unwrap = sinon.stub();
79+
})();
80+
const asyncConfig: AsyncMicroserviceOptions = {
81+
useFactory: () => ({ strategy }),
82+
inject: [],
83+
};
84+
85+
const instance = new NestMicroservice(
86+
mockContainer,
87+
asyncConfig,
88+
mockGraphInspector,
89+
mockAppConfig,
90+
);
91+
92+
expect((instance as any).serverInstance).to.equal(strategy);
93+
});
94+
95+
it('should call listen() on server when listen() is called', async () => {
96+
const listenSpy = sinon.spy((cb: () => void) => cb());
97+
const strategy = new (class extends Server {
98+
listen = listenSpy;
99+
close = sinon.spy();
100+
on = sinon.stub();
101+
unwrap = sinon.stub();
102+
})();
103+
104+
const instance = new NestMicroservice(
105+
mockContainer,
106+
{ strategy },
107+
mockGraphInspector,
108+
mockAppConfig,
109+
);
110+
111+
await instance.listen();
112+
expect(listenSpy.calledOnce).to.be.true;
113+
});
114+
115+
it('should delegate unwrap() to server', () => {
116+
const unwrapStub = sinon.stub().returns('core');
117+
const strategy = new (class extends Server {
118+
listen = sinon.spy();
119+
close = sinon.spy();
120+
on = sinon.stub();
121+
unwrap = unwrapStub;
122+
})();
123+
124+
const instance = new NestMicroservice(
125+
mockContainer,
126+
{ strategy },
127+
mockGraphInspector,
128+
mockAppConfig,
129+
);
130+
131+
expect(instance.unwrap()).to.equal('core');
132+
});
133+
134+
it('should delegate on() to server', () => {
135+
const onStub = sinon.stub();
136+
const strategy = new (class extends Server {
137+
listen = sinon.spy();
138+
close = sinon.spy();
139+
on = onStub;
140+
unwrap = sinon.stub();
141+
})();
142+
143+
const instance = new NestMicroservice(
144+
mockContainer,
145+
{ strategy },
146+
mockGraphInspector,
147+
mockAppConfig,
148+
);
149+
150+
const cb = () => {};
151+
instance.on('test:event', cb);
152+
expect(onStub.calledWith('test:event', cb)).to.be.true;
153+
});
154+
});

0 commit comments

Comments
 (0)