Open ChrisWun opened 2 years ago
This issue was also discovered around a year ago in #191 with an open PR to fix #194. The fix appears to work exactly as expected. I hope that it can be merged soon.
We had the same problem. I was not aware of this ticket before, so I've analyzed everything on my own already before. The cause for the timeout is because NestJS under the hood calls await on resolved DI tokens (object). Since object (mock) contains the then()
method it is considered as a promise and await
call wait on it to be resolved, but this never happens.
Why mocked object has .then()
method even, if this method was commented out from your code? Because Mocker calls .toString()
on a class to determine which methods it should mock. This class string is then parsed by regex in MockableFunctionsFinder and as an output we have also .then()
.
One possible workaround is what you already mention: deleting .then()
after mock is created. If you would like to solve this more generic without waiting ts-mockito fix and calling delete
in every test, you coul monkey patch MockableFunctionsFinder
via jest.setup.ts
or similar. See following code that we used:
export class TestUtil {
public static patchTsMockito(): void {
try {
const MockableFunctionsFinder = require('ts-mockito/lib/utils/MockableFunctionsFinder').MockableFunctionsFinder;
if (!MockableFunctionsFinder.prototype.isMockableOriginal) {
MockableFunctionsFinder.prototype.isMockableOriginal = MockableFunctionsFinder.prototype.isMockable;
MockableFunctionsFinder.prototype.isMockable = function (name: string): boolean {
if (['catch', 'then'].indexOf(name) >= 0) {
return false;
}
return this.isMockableOriginal(name);
};
}
} catch (error) {
console.warn('Failed to patch ts-mockito MockableFunctionsFinder', error);
}
}
}
By this fix .then()
and .catch()
methods are ignored - false
is returned by isMockable()
call. You can then simply call this patch method within jest.setup.ts
like:
TestUtil.patchTsMockito()
I use ts-mockito to test my NestJs application. Basically it works very well, but there are problems if the word "then" is somewhere in the code. If the word "then" is present, the created proxy object is assigned a function "then". When using NestJs with Jest, this leads to a timeout when using the mock by overriding a provider for dependency injection.
Results in:![Bildschirmfoto 2021-08-13 um 07 56 47](https://user-images.githubusercontent.com/7915105/129311621-7b73a35c-fb3c-4609-be27-62f7d1037a89.png)
It is also very strange that the Promise functions (then, resolve) are also added as a function on the proxy when the corresponding code has been commented out, but is inside a block of a function!
Results in:![Bildschirmfoto 2021-08-13 um 07 56 47](https://user-images.githubusercontent.com/7915105/129311621-7b73a35c-fb3c-4609-be27-62f7d1037a89.png)
As a workaround to be able to use the mocks with NestJs Dependency Injection, I remove the then property from the proxy:
delete foo['then']