I have a function that takes a lambda (and the lambda also takes an argument). How can I mock the function?
In the example below, I'm trying to mock connection.xmppStanzas
:
Example class:
type Matcher<T> = (t: T) => boolean;
const myMatcher: Matcher<Element> = (id: string) => ...;
class SomeClass {
constructor(private readonly idSource: IdSource,
private readonly connection: XmppConnection) {}
doSomething() {
const id = this.idSource.getId();
this.connection.xmppStanzas(myMatcher(id)).pipe(
...do something with the stanza
);
}
}
Test for SomeClass
:
describe('SomeClass', () => {
let idSource: IdSource;
let connection: XmppConnection;
let instance: SomeClass;
beforeEach(() => {
idSource = mock(idSource);
connection = mock(XmppConnection);
instance = new SomeClass(
instance(idSource),
instance(connection)
);
when(idSource.getId()).thenReturn(someId);
});
it('this is an example test', () => {
const stanzas$ = new BehaviorSubject(myTestStanza);
when(connection.xmppStanzas(myMatcher(someId))).thenReturn(stanzas$);
...test that the right thing was done with the stanza
verify(connection.xmppStanzas(myMatcher(someId))).once()
});
});
The problem is the when
doesn't return the stanzas stream (so all my tests to make sure something was done with the stanza fail) and the verify
I threw in at the end real quick also fails, proving why the when
isn't returning the right value: because tsmockito can't match the lambda. Apparently when you pass an argument to the lambda, it makes a new instance and even deepEqual
won't work on it.
I could do when(connection.xmppStanzas(anything())).thenReturn(stanzas$)
but I really want to make sure that my function doSomething()
is retrieving the ID correctly and passing it to my matcher. That's part of the test.
So my question is: how do I deal with mocking a function that takes a lambda that takes an argument??