Skip to content

Commit

Permalink
Merge pull request #45 from Markus-Ende/feature/mock-properties-witho…
Browse files Browse the repository at this point in the history
…ut-getters

Implement mocking for properties without getters by using es6 Proxy
  • Loading branch information
NagRock authored Oct 4, 2017
2 parents 9e9a187 + bc03ca6 commit a2faa92
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 2 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ let foo:Foo = instance(mockedFoo);
console.log(foo.sampleGetter);
```

### Stubbing property values that have no getters

Syntax is the same as with getter values.

Please note, that stubbing properties that don't have getters only works if [Proxy](http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-objects) object is available (ES6).

### Call count verification

``` typescript
Expand Down
18 changes: 17 additions & 1 deletion src/Mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,23 @@ export class Mocker {
}

public getMock(): any {
return this.mock;
if (typeof Proxy === "undefined") {
return this.mock;
}

return new Proxy(this.mock, this.createCatchAllHandlerForRemainingPropertiesWithoutGetters());
}

public createCatchAllHandlerForRemainingPropertiesWithoutGetters(): ProxyHandler<any> {
return {
get: (target: any, name: PropertyKey) => {
const hasMethodStub = name in target;
if (!hasMethodStub) {
this.createPropertyStub(name.toString());
this.createInstancePropertyDescriptorListener(name.toString(), {}, this.clazz.prototype);
}
return target[name];
}};
}

public reset(): void {
Expand Down
8 changes: 7 additions & 1 deletion src/ts-mockito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ export function when<T>(method: T): MethodStubSetter<T> {
}

export function instance<T>(mockedValue: T): T {
return (mockedValue as any).__tsmockitoInstance as T;
const tsmockitoInstance = (mockedValue as any).__tsmockitoInstance as T;
if (typeof Proxy === "undefined") {
return tsmockitoInstance;
}

const tsmockitoMocker = (mockedValue as any).__tsmockitoMocker as Mocker;
return new Proxy(tsmockitoInstance as any, tsmockitoMocker.createCatchAllHandlerForRemainingPropertiesWithoutGetters());
}

export function capture<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(method: (a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7, i: T8, j: T9) => any): ArgCaptor10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>;
Expand Down
1 change: 1 addition & 0 deletions src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"declaration": true,
"lib": [
"es5",
"es6",
"dom"
],
"types": [
Expand Down
63 changes: 63 additions & 0 deletions test/mocking.properties.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {MethodToStub} from "../src/MethodToStub";
import {instance, mock, verify, when} from "../src/ts-mockito";
import {Bar} from "./utils/Bar";

describe("mocking", () => {
let mockedFoo: FooWithProperties;
let foo: FooWithProperties;

describe("mocking object with properties (that don't have getters)", () => {
it("does create own property descriptors on mock after when is called", () => {
// given

// when
mockedFoo = mock(FooWithProperties);
when(mockedFoo.sampleNumber).thenReturn(42);

// then
expect((mockedFoo.sampleNumber as any) instanceof MethodToStub).toBe(true);
});

it("does create own property descriptors on instance", () => {
// given
mockedFoo = mock(FooWithProperties);
foo = instance(mockedFoo);

// when
when(mockedFoo.sampleNumber).thenReturn(42);

// then
expect(foo.sampleNumber).toBe(42);
});

it("works with verification if property is stubbed", () => {
// given
mockedFoo = mock(FooWithProperties);
foo = instance(mockedFoo);
when(mockedFoo.sampleNumber).thenReturn(42);

// when
const value = foo.sampleNumber;

// then
expect(() => verify(mockedFoo.sampleNumber).once()).not.toThrow();
});

it("works with verification if property is unstubbed", () => {
// given
mockedFoo = mock(FooWithProperties);
foo = instance(mockedFoo);

// when
const value = foo.sampleNumber;

// then
expect(() => verify(mockedFoo.sampleNumber).once()).not.toThrow();
});
});

});

class FooWithProperties {
public readonly sampleNumber: number;
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"declaration": true,
"lib": [
"es5",
"es6",
"dom"
],
"types": [
Expand Down

0 comments on commit a2faa92

Please sign in to comment.