From fa858e65aba49b05dc4778104c7724982d96e3ce Mon Sep 17 00:00:00 2001 From: johanblumenberg Date: Sun, 15 Dec 2019 13:12:43 +0100 Subject: [PATCH] Better error messages when failing call verification --- src/MethodStubVerificator.ts | 16 ++++++++++++---- src/utils/MethodCallToStringConverter.ts | 5 +++++ test/verification.spec.ts | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/MethodStubVerificator.ts b/src/MethodStubVerificator.ts index 1b77b40..d0f6049 100644 --- a/src/MethodStubVerificator.ts +++ b/src/MethodStubVerificator.ts @@ -7,6 +7,11 @@ const localSetTimeout = setTimeout; export class MethodStubVerificator { private methodCallToStringConverter: MethodCallToStringConverter = new MethodCallToStringConverter(); + private actualCalls() { + const calls = this.methodToVerify.mocker.getActionsByName(this.methodToVerify.methodName); + return 'Actual calls:\n ' + this.methodCallToStringConverter.convertActualCalls(calls).join('\n '); + } + constructor(private methodToVerify: MethodToStub) { methodToVerify.watcher.invoked(); } @@ -34,8 +39,9 @@ export class MethodStubVerificator { public times(value: number): void { const allMatchingActions = this.methodToVerify.mocker.getAllMatchingActions(this.methodToVerify.methodName, this.methodToVerify.matchers); if (value !== allMatchingActions.length) { - const methodToVerifyAsString = this.methodCallToStringConverter.convert(this.methodToVerify); - throw new Error(`Expected "${methodToVerifyAsString}to be called ${value} time(s). But has been called ${allMatchingActions.length} time(s).`); + const methodToVerifyAsString = this.methodCallToStringConverter.convert(this.methodToVerify); + const msg = `Expected "${methodToVerifyAsString}to be called ${value} time(s). But has been called ${allMatchingActions.length} time(s).`; + throw new Error(msg + '\n' + this.actualCalls()); } } @@ -43,7 +49,8 @@ export class MethodStubVerificator { const allMatchingActions = this.methodToVerify.mocker.getAllMatchingActions(this.methodToVerify.methodName, this.methodToVerify.matchers); if (value > allMatchingActions.length) { const methodToVerifyAsString = this.methodCallToStringConverter.convert(this.methodToVerify); - throw new Error(`Expected "${methodToVerifyAsString}to be called at least ${value} time(s). But has been called ${allMatchingActions.length} time(s).`); + const msg = `Expected "${methodToVerifyAsString}to be called at least ${value} time(s). But has been called ${allMatchingActions.length} time(s).`; + throw new Error(msg + '\n' + this.actualCalls()); } } @@ -51,7 +58,8 @@ export class MethodStubVerificator { const allMatchingActions = this.methodToVerify.mocker.getAllMatchingActions(this.methodToVerify.methodName, this.methodToVerify.matchers); if (value < allMatchingActions.length) { const methodToVerifyAsString = this.methodCallToStringConverter.convert(this.methodToVerify); - throw new Error(`Expected "${methodToVerifyAsString}to be called at least ${value} time(s). But has been called ${allMatchingActions.length} time(s).`); + const msg = `Expected "${methodToVerifyAsString}to be called at most ${value} time(s). But has been called ${allMatchingActions.length} time(s).`; + throw new Error(msg + '\n' + this.actualCalls()); } } diff --git a/src/utils/MethodCallToStringConverter.ts b/src/utils/MethodCallToStringConverter.ts index 6bc2566..91982ef 100644 --- a/src/utils/MethodCallToStringConverter.ts +++ b/src/utils/MethodCallToStringConverter.ts @@ -1,5 +1,6 @@ import {Matcher} from "../matcher/type/Matcher"; import {MethodToStub} from "../MethodToStub"; +import { MethodAction } from "../MethodAction"; export class MethodCallToStringConverter { public convert(method: MethodToStub): string { @@ -8,4 +9,8 @@ export class MethodCallToStringConverter { const stringifiedMatchers = method.matchers.map((matcher: Matcher) => matcher.toString()).join(", "); return `${method.methodName}(${stringifiedMatchers})" `; } + + public convertActualCalls(calls: MethodAction[]): string[] { + return calls.map(call => call.methodName + '(' + call.args.map(arg => arg.toString()).join(', ') + ')'); + } } diff --git a/test/verification.spec.ts b/test/verification.spec.ts index 5bb0a98..a525cb8 100644 --- a/test/verification.spec.ts +++ b/test/verification.spec.ts @@ -827,6 +827,24 @@ describe("verifying mocked object", () => { verify(mockedFoo.getBar()).once(); }); }); + + describe("matcher error messages", () => { + it("should describe expected method call", () => { + //given + instance(mockedFoo).getStringById(2); + + try { + // when + verify(mockedFoo.getStringById(1)).once(); + + expect(true).toBe(false); // Above call should throw an exception + } catch (e) { + // then + expect(e.message).toMatch(/getStringById\(strictEqual\(1\)\)/); + expect(e.message).toMatch(/getStringById\(2\)/); + } + }); + }); }); function verifyCallCountErrorMessage(error, expectedCallCount, receivedCallCount): void {