Skip to content

Commit b9a7bb7

Browse files
Adding support for mocking interfaces
1 parent 5537d50 commit b9a7bb7

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed

src/Mock.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export class Mocker {
1818
private mockableFunctionsFinder = new MockableFunctionsFinder();
1919
private objectPropertyCodeRetriever = new ObjectPropertyCodeRetriever();
2020

21-
constructor(private clazz: any, protected instance: any = {}) {
21+
constructor(private clazz: any, intf: boolean, protected instance: any = {}) {
22+
this.mock.__tsmockitoInterface = intf;
2223
this.mock.__tsmockitoInstance = this.instance;
2324
this.mock.__tsmockitoMocker = this;
2425
if (_.isObject(this.clazz) && _.isObject(this.instance)) {
@@ -40,11 +41,16 @@ export class Mocker {
4041
get: (target: any, name: PropertyKey) => {
4142
const hasMethodStub = name in target;
4243
if (!hasMethodStub) {
43-
this.createPropertyStub(name.toString());
44-
this.createInstancePropertyDescriptorListener(name.toString(), {}, this.clazz.prototype);
44+
if (this.mock.__tsmockitoInterface) {
45+
this.createMethodStub(name.toString());
46+
this.createInstanceActionListener(name.toString(), {});
47+
} else {
48+
this.createPropertyStub(name.toString());
49+
this.createInstancePropertyDescriptorListener(name.toString(), {}, this.clazz.prototype);
50+
}
4551
}
4652
return target[name];
47-
},
53+
}
4854
};
4955
}
5056

src/Spy.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export class Spy extends Mocker {
88
private realMethods: { [key: string]: RealMethod };
99

1010
constructor(instance: any) {
11-
super(instance.constructor, instance);
11+
super(instance.constructor, false, instance);
1212

1313
if (_.isObject(instance)) {
1414
this.processProperties(instance);

src/ts-mockito.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,18 @@ export function spy<T>(instanceToSpy: T): T {
3232
}
3333

3434
export function mock<T>(clazz: { new(...args: any[]): T; } | (Function & { prototype: T }) ): T {
35-
return new Mocker(clazz).getMock();
35+
return new Mocker(clazz, false).getMock();
36+
}
37+
38+
export function imock<T>(): T {
39+
class Empty {}
40+
let mockedValue = new Mocker(Empty, true).getMock();
41+
42+
if (typeof Proxy === "undefined") {
43+
return mockedValue;
44+
}
45+
var tsmockitoMocker = mockedValue.__tsmockitoMocker;
46+
return new Proxy(mockedValue, tsmockitoMocker.createCatchAllHandlerForRemainingPropertiesWithoutGetters());
3647
}
3748

3849
export function verify<T>(method: T): MethodStubVerificator<T> {

test/mocking.types.spec.ts

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {MethodToStub} from "../src/MethodToStub";
2-
import {instance, mock, when} from "../src/ts-mockito";
2+
import {instance, mock, imock, when, verify} from "../src/ts-mockito";
33
import {Bar} from "./utils/Bar";
44

55
describe("mocking", () => {
@@ -152,6 +152,41 @@ describe("mocking", () => {
152152

153153
});
154154
});
155+
156+
describe("mocking an interface", () => {
157+
let mockedFoo: SampleInterface;
158+
let foo: SampleInterface;
159+
160+
if (typeof Proxy !== "undefined") {
161+
162+
it("can verify call count", () => {
163+
// given
164+
mockedFoo = imock();
165+
foo = instance(mockedFoo);
166+
167+
// when
168+
let result = foo.sampleMethod();
169+
170+
// then
171+
verify(mockedFoo.sampleMethod()).called();
172+
expect(result).toBe(null);
173+
});
174+
175+
it("can setup call actions", () => {
176+
// given
177+
mockedFoo = imock();
178+
foo = instance(mockedFoo);
179+
when(mockedFoo.sampleMethod()).thenReturn(5);
180+
181+
// when
182+
let result = foo.sampleMethod();
183+
184+
// then
185+
verify(mockedFoo.sampleMethod()).called();
186+
expect(result).toBe(5);
187+
});
188+
}
189+
});
155190
});
156191

157192
abstract class SampleAbstractClass {

0 commit comments

Comments
 (0)