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

Adding support for verify(...).timeout(ms) #97

Open
wants to merge 2 commits 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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,16 @@ foo.bar();
console.log(capture(spiedFoo.bar).last()); // [42]
```

### Verify with timeout

This feature is useful when testing asynchronous functionality. You do some action and expect the result to arrive as an asynchronous function call to one of your mocks.

```typescript
let mockedFoo:Foo = mock(Foo);
await verify(mockedFoo.getBar(3)).timeout(1000);
```


### Thanks

* Szczepan Faber (https://www.linkedin.com/in/szczepiq)
Expand Down
24 changes: 24 additions & 0 deletions src/MethodStubVerificator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import {MethodToStub} from "./MethodToStub";
import {MethodCallToStringConverter} from "./utils/MethodCallToStringConverter";

// Save reference to setTimeout, in case tests are mocking time functions
const localSetTimeout = setTimeout;

export class MethodStubVerificator<T> {
private methodCallToStringConverter: MethodCallToStringConverter = new MethodCallToStringConverter();

Expand Down Expand Up @@ -91,4 +94,25 @@ export class MethodStubVerificator<T> {
throw new Error(`${errorBeginning}but none of them has been called.`);
}
}

public timeout(ms: number): Promise<void> {
return new Promise((resolve, reject) => {
const expired = Date.now() + ms;

const check = () => {
const allMatchingActions = this.methodToVerify.mocker.getAllMatchingActions(this.methodToVerify.name, this.methodToVerify.matchers);

if (allMatchingActions.length > 0) {
resolve();
} else if (Date.now() >= expired) {
const methodToVerifyAsString = this.methodCallToStringConverter.convert(this.methodToVerify);
reject(new Error(`Expected "${methodToVerifyAsString}to be called within ${ms} ms.`));
} else {
localSetTimeout(check, 1);
}
};

check();
});
}
}
55 changes: 54 additions & 1 deletion test/verification.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {instance, mock, verify} from "../src/ts-mockito";
import {instance, mock, verify, when} from "../src/ts-mockito";
import {MethodCallToStringConverter} from "../src/utils/MethodCallToStringConverter";
import {Bar} from "./utils/Bar";
import {Foo} from "./utils/Foo";
Expand Down Expand Up @@ -774,6 +774,59 @@ describe("verifying mocked object", () => {
});
});
});

describe("with timeout", () => {
it("should succeed if call already happend", async () => {
// given
foo.getBar();

// when
await verify(mockedFoo.getBar()).timeout(10000);

// then
verify(mockedFoo.getBar()).once();
});

it("should wait for call to happen", async () => {
// given
setTimeout(() => foo.getBar(), 10);

// when
await verify(mockedFoo.getBar()).timeout(10000);

// then
verify(mockedFoo.getBar()).once();
});

it("should fail if call does not happen", async () => {
// given

// when
let error;
try {
await verify(mockedFoo.getBar()).timeout(10);
} catch (e) {
error = e;
}

// then
expect(error.message).toContain("to be called within");
});

it("should not alter call expectations", async () => {
// given
let result: string;
when(mockedFoo.getBar()).thenReturn("abc");
setTimeout(() => result = foo.getBar(), 10);

// when
await verify(mockedFoo.getBar()).timeout(10000);

// then
expect(result).toEqual("abc");
verify(mockedFoo.getBar()).once();
});
});
});

function verifyCallCountErrorMessage(error, expectedCallCount, receivedCallCount): void {
Expand Down