Files
java-testing-lab/mockito/src/test/java/lab/mockito/StrictnessTest.java
T

104 lines
4.4 KiB
Java

package lab.mockito;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoSession;
import org.mockito.exceptions.misusing.PotentialStubbingProblem;
import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
import org.mockito.quality.Strictness;
/** Uses the MockitoSession API so the strictness failures can be caught and recorded. */
class StrictnessTest {
private static void finish(MockitoSession session) {
try {
session.finishMocking();
} catch (UnnecessaryStubbingException ignored) {
// the demo stubs are deliberately left unused in some tests
}
}
private MockitoSession strict() {
return org.mockito.Mockito.mockitoSession().strictness(Strictness.STRICT_STUBS).startMocking();
}
@Test
void unusedStubIsReportedWhenTheSessionEnds() {
Transcript t = new Transcript("10-unnecessary-stubbing.txt");
MockitoSession session = strict();
PaymentGateway gateway = mock(PaymentGateway.class);
when(gateway.isAvailable()).thenReturn(true); // used below
when(gateway.charge("acc-1", 100)).thenReturn(null); // never used
gateway.isAvailable();
UnnecessaryStubbingException e = assertThrows(UnnecessaryStubbingException.class, session::finishMocking);
t.block("UnnecessaryStubbingException:", e.getMessage());
t.write();
}
@Test
void sameMethodDifferentArgumentsIsAPotentialStubbingProblem() {
Transcript t = new Transcript("11-potential-stubbing-problem.txt");
MockitoSession session = strict();
try {
PaymentGateway gateway = mock(PaymentGateway.class);
when(gateway.isAvailable()).thenReturn(true);
when(gateway.charge("acc-1", 900)).thenReturn(new Receipt("r", "acc-1", 900, true));
CheckoutService svc = new CheckoutService(gateway, mock(AuditLog.class), new PriceCalculator());
// 1000 cents with 0% discount reaches charge("acc-1", 1000) inside CheckoutService.java,
// a different source file from this test: Mockito flags the argument mismatch.
PotentialStubbingProblem e = assertThrows(PotentialStubbingProblem.class, () -> svc.checkout("acc-1", 1000, 0));
t.block("PotentialStubbingProblem:", e.getMessage());
} finally {
finish(session);
}
t.write();
}
@Test
void sameFileMismatchIsNotFlagged() {
Transcript t = new Transcript("11b-same-file-mismatch-not-flagged.txt");
MockitoSession session = strict();
try {
PaymentGateway gateway = mock(PaymentGateway.class);
when(gateway.charge("acc-1", 900)).thenReturn(new Receipt("r", "acc-1", 900, true));
// Same call-shape as the test above, but made from this very file.
Receipt r = assertDoesNotThrow(() -> gateway.charge("acc-1", 1000));
t.line("charge(\"acc-1\", 1000) from the test file returns : %s (no PotentialStubbingProblem)", r);
assertNull(r);
} finally {
finish(session);
}
t.write();
}
@Test
void lenientStubsAreExemptAndStrictnessCanBeLoosenedPerStub() {
Transcript t = new Transcript("12-lenient.txt");
MockitoSession session = strict();
PaymentGateway gateway = mock(PaymentGateway.class);
lenient().when(gateway.charge("acc-1", 100)).thenReturn(new Receipt("r", "acc-1", 100, true));
lenient().when(gateway.isAvailable()).thenReturn(true);
Receipt other = gateway.charge("acc-1", 999); // arg mismatch, but the stub is lenient
t.line("lenient stub, mismatching call returns : %s", other);
assertNull(other);
session.finishMocking(); // unused lenient stub: no exception
t.line("finishMocking with unused lenient stubs : no exception");
t.write();
}
@Test
void plainMockWithoutSessionIsLenient() {
Transcript t = new Transcript("13-no-session-no-checks.txt");
PaymentGateway gateway = mock(PaymentGateway.class);
when(gateway.charge("acc-1", 100)).thenReturn(new Receipt("r", "acc-1", 100, true));
Receipt other = gateway.charge("acc-1", 999);
t.line("mismatching call on a plain mock returns : %s (no strictness error)", other);
assertNull(other);
t.write();
}
}