diff --git a/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java b/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java index a3e046c479..5e463c7288 100644 --- a/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java +++ b/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java @@ -46,6 +46,18 @@ public MockitoAssertionError(MockitoAssertionError error, String message) { unfilteredStackTrace = error.getUnfilteredStackTrace(); } + /** + * Creates a copy of the given assertion error with the custom failure message prepended. + * @param error The assertion error to copy + * @param message The custom message to prepend + * @since 3.3.13 + */ + public MockitoAssertionError(AssertionError error, String message) { + super(message + "\n" + error.getMessage()); + unfilteredStackTrace = error.getStackTrace(); + super.setStackTrace(unfilteredStackTrace); + } + public StackTraceElement[] getUnfilteredStackTrace() { return unfilteredStackTrace; } diff --git a/src/main/java/org/mockito/internal/verification/Description.java b/src/main/java/org/mockito/internal/verification/Description.java index d9c133e03d..7732ceb98e 100644 --- a/src/main/java/org/mockito/internal/verification/Description.java +++ b/src/main/java/org/mockito/internal/verification/Description.java @@ -41,6 +41,8 @@ public void verify(VerificationData data) { } catch (MockitoAssertionError e) { throw new MockitoAssertionError(e, description); + } catch (AssertionError e) { + throw new MockitoAssertionError(e, description); } } } diff --git a/src/test/java/org/mockito/DescriptionTest.java b/src/test/java/org/mockito/DescriptionTest.java new file mode 100644 index 0000000000..32565e4b6c --- /dev/null +++ b/src/test/java/org/mockito/DescriptionTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020 Mockito contributors + * This program is made available under the terms of the MIT License. + */ +package org.mockito; + +import static org.mockito.Mockito.*; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.exceptions.base.MockitoAssertionError; + +/** + * Tests for https://github.com/mockito/mockito/issues/1712 + */ +public class DescriptionTest { + @Rule public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void verify_method_not_called_should_include_description_in_report() { + final String description = "Failed to call doSomethingElse"; + expectedException.expect(MockitoAssertionError.class); + expectedException.expectMessage(description); + + Dependency dependency = spy(Dependency.class); + SystemUnderTest systemUnderTest = new SystemUnderTest(); + systemUnderTest.doNothing(dependency); + verify(dependency, description(description)).doSomethingElse(false); + } + + @Test + public void + verify_method_called_with_unexpected_argument_should_include_description_in_report() { + final String description = "Failed to call doSomethingElse with expected argument"; + expectedException.expect(MockitoAssertionError.class); + expectedException.expectMessage(description); + + Dependency dependency = spy(Dependency.class); + SystemUnderTest systemUnderTest = new SystemUnderTest(); + systemUnderTest.doSomething(dependency); + verify(dependency, description(description)).doSomethingElse(false); + } + + static class SystemUnderTest { + @SuppressWarnings("unused") + void doNothing(Dependency dependency) {} + + void doSomething(Dependency dependency) { + dependency.doSomethingElse(true); + } + } + + static class Dependency { + @SuppressWarnings("unused") + void doSomethingElse(boolean value) {} + } +} diff --git a/src/test/java/org/mockito/internal/verification/DescriptionTest.java b/src/test/java/org/mockito/internal/verification/DescriptionTest.java index 5444ca342f..224aa02f06 100644 --- a/src/test/java/org/mockito/internal/verification/DescriptionTest.java +++ b/src/test/java/org/mockito/internal/verification/DescriptionTest.java @@ -51,4 +51,28 @@ public void verification_failure_should_prepend_expected_message() { assertEquals(expectedResult, e.getMessage()); } } + + /** + * Test of verify method, of class Description. This test validates that the custom message is prepended to the + * error message when verification fails and throws a Throwable which is not a MockitoAssertionError. + */ + @Test + public void verification_failure_throwing_AssertionError_should_prepend_expected_message() { + String failureMessage = "message should be prepended to the original message"; + String exceptionMessage = "original error message"; + String expectedResult = failureMessage + "\n" + exceptionMessage; + AssertionError error = new AssertionError(exceptionMessage); + doThrow(error).when(mockVerificationMode).verify(mockVerificationData); + + Description instance = new Description(mockVerificationMode, failureMessage); + + try { + instance.verify(mockVerificationData); + verify(mockVerificationMode).verify(mockVerificationData); + fail("Should not have made it this far"); + + } catch (MockitoAssertionError e) { + assertEquals(expectedResult, e.getMessage()); + } + } }