Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cfo2K4u4rF18QsPXPFnytf
104 lines
4.4 KiB
Java
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();
|
|
}
|
|
}
|