ts-mockito
ts-mockito copied to clipboard
Promise hangs when resolving a mocked instance
When a Promise wraps a mocked instance, it never resolves but hangs.
const { mock, instance } = require('ts-mockito')
const MockConnector = mock()
const connector = instance(MockConnector)
function connectorFactory() {
return Promise.resolve(connector) // <== This mock instance (Proxy object) never get resolved by Promise.
}
(async () => {
const created = await connectorFactory() // <== This Promise hangs forever.
console.log('Connector created') // <== Never reached
})()
This issue is same with #155 which never gets noticed nor replied. A runnable sandbox: https://runkit.com/embed/5ljjgubxm9fm
I can propose a fix: to add "then" to excluded property at this line in Mock.ts
private excludedPropertyNames: string[] = ["hasOwnProperty", "then"];
It is because Promise and functions marked with "async" keyword look for "then" method in resolved/returned value, if "then" exists as a function, they will regard the value as a Promise and attempt to resolve it.
For now, this is my workaround
JavaScript:
const {
mock, // Don't use this
instance,
} = require('ts-mockito')
const { Mocker } = require('ts-mockito/lib/Mock') // Must be below require('ts-mockito')
function betterMock(clazz) {
const mocker = new Mocker(clazz)
mocker['excludedPropertyNames'] = ['hasOwnProperty', 'then']
return mocker.getMock()
}
TypeScript:
import {
mock, // Don't use this
instance
} from 'ts-mockito'
import { Mocker } from 'ts-mockito/lib/Mock' // Must be below import 'ts-mockito'
function betterMock<T>(clazz?: (new(...args: any[]) => T) | (Function & { prototype: T }) ): T {
const mocker = new Mocker(clazz)
mocker['excludedPropertyNames'] = ['hasOwnProperty', 'then']
return mocker.getMock()
}
Useage example:
const {
mock, // Don't use this
instance,
} = require('ts-mockito')
const { Mocker } = require('ts-mockito/lib/Mock') // Must be below require('ts-mockito')
function betterMock(clazz) {
const mocker = new Mocker(clazz)
mocker['excludedPropertyNames'] = ['hasOwnProperty', 'then']
return mocker.getMock()
}
const MockConnector = betterMock() // Instead of mock()
const connector = instance(MockConnector)
function connectorFactory() {
return Promise.resolve(connector) // <== This mock instance can be resolved by Promise.
}
(async () => {
const created = await connectorFactory() // <== This Promise resolves.
console.log('Connector created') // <== Reached!
})()
@hirikarate your workaround works for me. You saved my day. Thank you very much for sharing!!
oy, this is my issue...
One solution could be to expose the excluded properties list in an options argument to the mock()
function - something like mock(SouldNotBeThenable, { omitHandlersForProperties: [ 'then' ] })
. This might be better than simply adding 'then' to the excluded properties list so that mocking the then()
method is still allowed.
Are there any updates on this issue?
@NagRock why this issue has not been addressed for such a long time?
Don't like to spam, but it may have some value - it works without an issue with @johanblumenberg fork.
At this moment this is only issue which holds some projects which I am involved in from switching back to main repo.
Your workaround works for my case as well. Thanks! @hirikarate