I have a simple unit test that uses Substitute.js (also tried this with TypeMoq mocks and the behavior I'll describe is the same).
In this test I try the simplest thing, using the of
operator to emit the mocked object. Without any further operators, the subscribe callback is never called. Example :
import {Arg, Substitute, SubstituteOf} from "@fluffy-spoon/substitute";
import "reflect-metadata";
import {Observable, of} from "rxjs";
const factory = Substitute.for<MessageFactory>();
of(factory).subscribe((f) => console.log("got it"));
The console log is never called.
Now, if I don't use the operator and I just create an observable, the log is working. Example :
import {Arg, Substitute, SubstituteOf} from "@fluffy-spoon/substitute";
import "reflect-metadata";
import {Observable, of} from "rxjs";
const factory = Substitute.for<MessageFactory>();
new Observable((subscriber) => {
subscriber.next(factory);
subscriber.complete();
}).subscribe((f) => console.log("got it"));
Any clues on what's going on with the of
operator in this case?
I'm using :
of()
method has one special use-case where you pass as the last argument an instance of RxJS Scheduler
(This use-case is deprecated and will be removed in RxJS 8).
https://github.com/ReactiveX/rxjs/blob/master/src/internal/observable/of.ts#L9
For example you could do the following:
of(1, 2, 3, asyncScheduler)
Since Substitute.for<MessageFactory>()
returns a function
(try typeof factory
) of()
thinks you're passing a scheduler. Substitute.for
in fact returns Proxy
under the hood which confuses RxJS check. So for this reason it never emits anything.
Anyway, you can do for example this:
from([factory]).subscribe((f) => console.log("got it"));
very nice catch! Thank you. So that means that until RxJS 8, I have to avoid "of" in my production code as well because mocked parameters will not work during unit testing. Unless there's some other way of bypassing this?
of()
works fine with any value including functions likeof(() => {})
but this is a special use-case where it doesn't know how to handleProxy
objects. If you use mocked objects withof()
then I'm afraid there's no other way than not usingof()
right now.I'll file an issue on RxJS's GitHub page tomorrow. You might not be the only one who encountered this.