-
Notifications
You must be signed in to change notification settings - Fork 0
/
iris.test-server.ts
109 lines (88 loc) · 2.86 KB
/
iris.test-server.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
105
106
107
108
109
import * as irisTesting from '@iris-events/iris/testing'
import { SetMetadata } from '@nestjs/common'
import { IrisServer } from '../iris.server'
/**
* IrisServer intended for testing
* allows for spying on handler methods which is otherwise
* not directly supported by NestJS
*/
export class IrisTestServer<MockT> extends IrisServer {
protected readonly TAG = IrisTestServer.name
static handlerSpies: Map<string, (...args: unknown[]) => unknown> = new Map()
static mockFn: () => (...args: unknown[]) => unknown
static setMockFn(fn: () => (...args: unknown[]) => unknown) {
IrisTestServer.mockFn = fn
}
protected decorateHandlers(): void {
super.decorateHandlers()
this.replaceHandlerCallbacks()
}
get handlerSpies() {
return IrisTestServer.handlerSpies
}
getIrisHandlers() {
return this.handlers
}
getIrisHandlerMetas() {
return this.handlers.map((handler) => handler.meta)
}
async clearQueues(alsoDelete: boolean, allowReconnect = false) {
return irisTesting.utilities.clearQueues(
this.getIrisHandlerMetas(),
alsoDelete,
allowReconnect,
)
}
/**
* Returns a spy for a given message class
*/
public getSpyForHandler<T, MockE = MockT>(
handlerClass: new () => T,
methodName: keyof T,
): MockE {
const handler = this.handlers.find(
(handler) =>
handler.instanceWrapper.metatype === handlerClass &&
handler.meta.methodName === methodName,
)
if (!handler) {
throw new Error(
`No @MessageHandler() handler available on ${handlerClass.name}.${<
string
>methodName}()`,
)
}
const pattern = this.getHandlerPatternForExchange(handler.meta)
return <MockE>this.handlerSpies.get(pattern)!
}
/**
* Replaces all methods on handler's prototype
* with anonymous methods which then proxy the
* calls to dedicated spies and original handlers.
*/
protected replaceHandlerCallbacks() {
for (const handler of this.handlers) {
const pattern = this.getHandlerPatternForExchange(handler.meta)
if (!this.handlerSpies.has(pattern)) {
this.handlerSpies.set(pattern, IrisTestServer.mockFn())
}
const spy = this.handlerSpies.get(pattern)
const originalFn =
handler.instanceWrapper.instance[handler.meta.methodName]
handler.instanceWrapper.instance.constructor.prototype[
handler.meta.methodName
] = async (...args: unknown[]) => {
spy!.apply(spy, args)
return await originalFn.apply(handler.instanceWrapper.instance, args)
}
const targetFn =
handler.instanceWrapper.instance.constructor.prototype[
handler.meta.methodName
]
const keys = Reflect.getMetadataKeys(originalFn)
for (const key of keys) {
SetMetadata(key, Reflect.getMetadata(key, originalFn))(targetFn)
}
}
}
}