NagRock / ts-mockito

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

Mocking a single method #182

Open gCardinal opened 4 years ago

gCardinal commented 4 years ago

Is ts-mockito able to mock a single function? I've been trying without much success and I'm worried that it's not a supported use case... This lib has been a real blessing to work with so far (it's still pretty new to me) I'd hate to have to switch back to sinon...

Anyway, to a concrete example:

export type GameResponseNormalizer = (response: Promise<any>) => Game
export interface RestClient {
    post: (uri: string, params: object)
}

export const createGame = (client: RestClient, normalizer: GameResponseNormalizer): Promise<Game> => {
    // ... Boring implementation
}

Creating a mock for RestClient is pretty basic, but would ts-mockito be able to create a mock for GameResponseNormalizer?

Sometimes it's just not worth building a whole class for very simple behaviors or methods. Especially in a functional language like JS or TS.

AnthonyIacono commented 4 years ago

I'm not sure I understand. Couldn't you just pass your own method into the normalizer parameter when calling the methods? Can you write how you would expect to mock it if it were supported?

gCardinal commented 4 years ago

Right, of course, but then I won't be able to assert if the method was called and if it was, that it was properly called.

I'm not sure how I would see the interface for mocking a function though without adding a different mock() method. Maybe passing mock() a method as a parameter would allow us to mock the method and then provide a default return type, further customization of the mock would be done with with() since when() wouldn't really make sense here...

A bit like this maybe?

// With my example above
export type GameResponseNormalizer = (response: Promise<any>) => Game

// Then to mock this
const normalizer = mock<GameResponseNormalizer >(() => ({id: 2})
normalizer.with(anyNumber()).thenThrow(new Error("Nope"));

// We could then assert it was called properly in a test like so:
verify(normalizer(anything())).once()

I have never worked on a mocking library so I have no idea if this proposed API would even make sense.

I should note that I managed to do it with what's currently offered, but it's pretty clumsy.

const normalizer = mock<{normalizer: GameResponseNormalizer}>()
when(normalizer.normalize(anyString())).thenReturn('Something')

// Then I need to pass the mocked function this way
createGame(whatever, instance(normalizer).normalize)

// Now I can assert the normalizer was properly called
verify(normalizer.normalize(anyString()).atLeast(1)
gCardinal commented 4 years ago

Just saw this PR.