ts-mockito icon indicating copy to clipboard operation
ts-mockito copied to clipboard

Feature request: option to throw instead of returning `null` for non-mocked properties

Open abel-matsec opened this issue 2 years ago • 3 comments

When writing tests, I like to require explicitly mocking all properties of a mock object that end up getting used by my code. Is there a way for a mock to immediately raise if any property is accessed that has not been mocked via a call to when?

The other thing that irks me about returning null by default is that the mock object may not actually be abiding by it's type, leading to potentially unexpected behavior when writing tests using mocks.

abel-matsec avatar Dec 13 '23 21:12 abel-matsec

Here's a bit of a hack...

export class StrictMocker extends Mocker {
    protected getEmptyMethodStub(key: string, args: any[]): MethodStub {
        return new ThrowErrorMethodStub(-1, [], new Error(`${key} not mocked`));
    }
}

// These mimic the overloaded function signature of `mock`
// eslint-disable-next-line @typescript-eslint/ban-types
export function strictMock<T>(clazz: (new (...args: any[]) => T) | (Function & { prototype: T })): T;
export function strictMock<T>(clazz?: any): T;
export function strictMock<T>(clazz?: any): T {
    return new StrictMocker(clazz).getMock();
}

abel-matsec avatar Dec 13 '23 22:12 abel-matsec

For your first point, I think you can accomplish that with spies, instead of creating a new API:

const objInstance = {} as unknown as MyClass;
const spiedInstance = spy(objInstance);

when(spiedInstance.existingFunction()).thenReturn('foobar');

spiedInstance.existingFunction(); // returns 'foobar'
spiedInstance.nonExistingFunction(); // throws

roypeled avatar Jul 14 '24 14:07 roypeled

For you second point, not sure that this is the correct behavior (you need to specify exactly what output you want to get from mocks with when clauses), and it would introduce a whole new layer of complexity where we would require users of ts-mockito to compile the code with type reflection (so we would know at runtime what type is for each field).

I think if you want an actual mock that contains values that match its type definition, there are other libraries to do so.

roypeled avatar Jul 14 '24 14:07 roypeled