Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add defer() for testing deferred promise resolution #141

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ when(mockedFoo.fetchData("a")).thenResolve({id: "a", value: "Hello world"});
when(mockedFoo.fetchData("b")).thenReject(new Error("b does not exist"));
```

### Defer resolving promises

The actions `.thenResolve()` and `.thenReject()` are returning promises that are already resolved or rejected. Sometimes you want to control the order or timing of when promises are resolved. In that case it is useful to return a deferred promise, and resolve it from the test code, when appropriate.

```typescript
let d = defer<number>();
when(obj.method()).thenReturn(d); // Return a promise that is not resolved yet

d.resolve(1); // Later, the promise is resolved or rejected
```

### Resetting mock calls

You can reset just mock call counter
Expand Down
17 changes: 17 additions & 0 deletions src/ts-mockito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ export function objectContaining(expectedValue: Object): any {
return new ObjectContainingMatcher(expectedValue) as any;
}

export type Deferred<T> = Promise<T> & {
resolve: (value: T) => void;
reject: (err: any) => void;
};

export function defer<T>(): Deferred<T> {
let resolve: (value: T) => void;
let reject: (err: any) => void;

const d = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return Object.assign(d, { resolve, reject });
}

// Export default object with all members (ember-browserify doesn't support named exports).
export default {
spy,
Expand All @@ -144,4 +160,5 @@ export default {
strictEqual,
match,
objectContaining,
defer,
};
35 changes: 35 additions & 0 deletions test/defer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { anything, defer, fnmock, instance, mock, verify, when } from "../src/ts-mockito";

class MockObject {
public method(): Promise<number> {
return Promise.resolve(100);
}
}

describe("defer", () => {
it("resolves a promise", async () => {
const resolved: (value: number) => void = fnmock();
const obj: MockObject = mock(MockObject);
const d = defer<number>();
when(obj.method()).thenReturn(d);

instance(obj).method().then(instance(resolved));
verify(resolved(anything())).never();

d.resolve(1);
await verify(resolved(1)).timeout(100);
});

it("rejects a promise", async () => {
const rejected: (err: any) => void = fnmock();
const obj: MockObject = mock(MockObject);
const d = defer<number>();
when(obj.method()).thenReturn(d);

instance(obj).method().catch(instance(rejected));
verify(rejected(anything())).never();

d.reject(1);
await verify(rejected(1)).timeout(100);
});
});