florinn/typemoq

Using mocks as return values for mocks is impossible

Closed this issue · 0 comments

I'm trying to mock the IndexedDB IDBFactory and it's return values (this is a real scenario for which I have no control over the interface). IDBOpenDBRequest has a property (result) that returns an object (IDBDatabase) that needs to be mocked. Because everything is cloned (including return values from properties):

  1. MockBehavior.Strict throws immediately on properties such as length (as lodash probes the object for array likeness etc. during clone).
  2. verifyAll() doesn't work, as the clone targets some unknown (likely) cloned interceptor.
var behavior = MockBehavior.Strict; // Or Loose for (2)

interface Foo {
    someMethod(): void;
}
  
interface Bar {
    readonly foo: Foo;
}

var foo = Mock.ofType<Foo>(undefined, behavior);
foo.setup(x => x.someMethod()).verifiable(Times.once());

var bar = Mock.ofType<Bar>(undefined, behavior);
bar.setup(x => x.foo).returns(() => foo.object);

// Act
// 1. MockException is thrown as `length` is not mocked.
console.log(bar.object.foo);

// Assert
// 2. The method is called on the clone, which means it is not called on the value provided by foo.
foo.verifyAll();

There is no other way to solve the specific scenario I'm testing, and this does work in Moq.