NagRock / ts-mockito

Mocking library for TypeScript
MIT License
969 stars 93 forks source link

(instance(mock(MyClass)) instanceof MyClass) is false. #204

Open yuyasasaki-0 opened 3 years ago

yuyasasaki-0 commented 3 years ago

The mock instance from ts-mockito does not return true with instanceof.

const mockedInstanceOfMyClass = instance(mock(MyClass))
console.log(mockedInstanceOfMyClass  instanceof MyClass) // false, should be true

Thus, when I test my code like following with the mock instance (Proxy), I cannot test as I intended.

if (myArg instanceof MyClass) {
  foo()
} else {
  ...

I can manually set the prototype of parent class to my mock instance with Object.setPrototypeOf() and pass the test of code with instanceof without modification, but it's natural that the mock instance of a class is the instance of the class by default.

prKassad commented 3 years ago

I also encountered a problem checking instanceof in my code. This doesn't seem to be possible to check via the mock object. See https://github.com/NagRock/ts-mockito/issues/133#issuecomment-463142976. If anyone has any ideas on how to test this without changing the existing code, please tell us.

prKassad commented 3 years ago

I'am hacked it's via Symbol.hasInstance and duck typing in my test:

Object.defineProperty(MyClass, Symbol.hasInstance, {
  value: (obj) => obj.hasOwnProperty("myProperty"),
});
const mockedMyClass = mock(MyClass);
when(mockedMyClass.myProperty).thenReturn(true);
Lagyu commented 3 years ago

If anyone has any ideas on how to test this without changing the existing code, please tell us.

@prKassad As mentioned in the first comment, Object.setPrototypeOf lets you test code with instanceof without change of existing code.

const mockedInstanceOfMyClass = instance(mock(MyClass))
console.log(mockedInstanceOfMyClass instanceof MyClass) // false
Object.setPrototypeOf(mockedInstanceOfMyClass, MyClass.prototype)
console.log(mockedInstanceOfMyClass instanceof MyClass) // true
jandk008 commented 3 years ago

This one should take more attention for getting ts-mockito more intuitive and convenient

wenPKtalk commented 1 year ago

Nice! This is right

jakobsa commented 1 year ago

how about:

import {instance as wrappedInstance} from 'ts-mockito';

const instance = function(mockClass) {
    const mockedInstanceOfMyClass = wrappedInstance(mockClass)
    Object.setPrototypeOf(mockedInstanceOfMyClass, mockClass.__tsmockitoMocker.clazz.prototype);
    return mockedInstanceOfMyClass;
}