Add junit-mockito module: 30 runnable JUnit 6.1.3 / Mockito 5.24.0 interview answers
One test per question, each writing and asserting its own transcript under output/. Covers lifecycle, extensions, parameterized and dynamic tests, mocks vs spies, verification, strict stubs, static and constructor mocking, and flaky tests. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01CifR2BE7PBvRy5hT8TS9oz
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
TestEngines found on the classpath (ServiceLoader<TestEngine>):
|
||||
junit-jupiter 6.1.3
|
||||
Jupiter API version : 6.1.3
|
||||
Platform launcher : 6.1.3
|
||||
Platform engine API : 6.1.3
|
||||
junit-vintage engine : not on the classpath
|
||||
@@ -0,0 +1,2 @@
|
||||
junit-jupiter-api 5.14.4 : class-file major version 52 (Java 8), MethodOrderer$Alphanumeric entries in jar: 1
|
||||
junit-jupiter-api 6.1.3 : class-file major version 61 (Java 17), MethodOrderer$Alphanumeric entries in jar: 0
|
||||
@@ -0,0 +1,3 @@
|
||||
class-file major version of org.junit.jupiter.api.Test : 61 (Java 17)
|
||||
Class.forName("org.junit.jupiter.api.MethodOrderer$Alphanumeric") -> ClassNotFoundException
|
||||
(the 5.14.4 versus 6.1.3 jar comparison is scripts/compare-5-vs-6.sh -> q02-jar-comparison.txt)
|
||||
@@ -0,0 +1,8 @@
|
||||
@BeforeAll (static)
|
||||
@BeforeEach on instance #1
|
||||
test second() on instance #1
|
||||
@AfterEach on instance #1
|
||||
@BeforeEach on instance #2
|
||||
test first() on instance #2
|
||||
@AfterEach on instance #2
|
||||
@AfterAll (static)
|
||||
@@ -0,0 +1,3 @@
|
||||
@BeforeAll (non-static) on instance #1
|
||||
second(): instance #1, counter=1
|
||||
first(): instance #1, counter=2
|
||||
@@ -0,0 +1,8 @@
|
||||
outer @BeforeEach
|
||||
outerTest()
|
||||
outer @AfterEach
|
||||
outer @BeforeEach
|
||||
inner @BeforeEach
|
||||
innerTest()
|
||||
inner @AfterEach
|
||||
outer @AfterEach
|
||||
@@ -0,0 +1,4 @@
|
||||
declared order in the source : zebra(), apple(), mango(), banana()
|
||||
default (no orderer configured) : [banana(), apple(), mango(), zebra()]
|
||||
MethodOrderer.MethodName : [apple(), banana(), mango(), zebra()]
|
||||
MethodOrderer.DisplayName : [apple(), banana(), mango(), zebra()]
|
||||
@@ -0,0 +1,5 @@
|
||||
assertAll reported 2 failures from 3 assertions:
|
||||
order (2 failures)
|
||||
org.opentest4j.AssertionFailedError: quantity ==> expected: <1> but was: <2>
|
||||
org.opentest4j.AssertionFailedError: code ==> expected: <A> but was: <B>
|
||||
assertThrows returns the exception: getMessage() = boom
|
||||
@@ -0,0 +1,4 @@
|
||||
assertTimeout runs the code on the test thread : true
|
||||
assertTimeoutPreemptively runs the code on the test thread : false
|
||||
assertTimeout failure message (trimmed at ' by '): execution exceeded timeout of 50 ms
|
||||
assertTimeoutPreemptively failure message: execution timed out after 50 ms
|
||||
@@ -0,0 +1,3 @@
|
||||
assertionFails() -> FAILED
|
||||
assumptionFails() -> ABORTED
|
||||
passes() -> SUCCESSFUL
|
||||
@@ -0,0 +1,8 @@
|
||||
declared: beforeAll
|
||||
declared: beforeEach
|
||||
test class: @BeforeEach method
|
||||
declared: beforeTestExecution
|
||||
test class: the test body
|
||||
declared: afterTestExecution
|
||||
declared: afterEach
|
||||
declared: afterAll
|
||||
@@ -0,0 +1,13 @@
|
||||
declared: beforeAll
|
||||
programmatic(static field): beforeAll
|
||||
declared: beforeEach
|
||||
programmatic(static field): beforeEach
|
||||
declared: beforeTestExecution
|
||||
programmatic(static field): beforeTestExecution
|
||||
test body
|
||||
programmatic(static field): afterTestExecution
|
||||
declared: afterTestExecution
|
||||
programmatic(static field): afterEach
|
||||
declared: afterEach
|
||||
programmatic(static field): afterAll
|
||||
declared: afterAll
|
||||
@@ -0,0 +1,2 @@
|
||||
custom parameter : Tenant[name=tenant-for-resolvesCustomAndBuiltIn]
|
||||
built-in TestInfo: displayName=resolvesCustomAndBuiltIn(Tenant, TestInfo)
|
||||
@@ -0,0 +1,12 @@
|
||||
enumSource(Level) / [1] LOW -> SUCCESSFUL
|
||||
enumSource(Level) / [2] HIGH -> SUCCESSFUL
|
||||
valueSource(int) / [1] 1 -> SUCCESSFUL
|
||||
valueSource(int) / [2] 2 -> SUCCESSFUL
|
||||
valueSource(int) / [3] 3 -> SUCCESSFUL
|
||||
nullAndEmpty(String) / [1] null -> SUCCESSFUL
|
||||
nullAndEmpty(String) / [2] "" -> SUCCESSFUL
|
||||
nullAndEmpty(String) / [3] " " -> SUCCESSFUL
|
||||
csvSource(String, int) / [1] "apple", "1" -> SUCCESSFUL
|
||||
csvSource(String, int) / [2] "banana", "2" -> SUCCESSFUL
|
||||
methodSource(String, int) / [1] "x", 10 -> SUCCESSFUL
|
||||
methodSource(String, int) / [2] "y", 20 -> SUCCESSFUL
|
||||
@@ -0,0 +1,11 @@
|
||||
display name: csv(String, String) / [1] a="x" b=null -> SUCCESSFUL
|
||||
display name: csv(String, String) / [2] a=null b="y" -> SUCCESSFUL
|
||||
display name: csv(String, String) / [3] a="" b="z" -> SUCCESSFUL
|
||||
display name: csv(String, String) / [4] a=null b="w" -> SUCCESSFUL
|
||||
display name: csv(String, String) / [5] a="a,b" b="q" -> SUCCESSFUL
|
||||
--- values the test method received ---
|
||||
a="x" b=null
|
||||
a=null b="y"
|
||||
a="" b="z"
|
||||
a=null b="w"
|
||||
a="a,b" b="q"
|
||||
@@ -0,0 +1,4 @@
|
||||
@BeforeEach ran (1 time so far)
|
||||
squares() / square of 1 -> SUCCESSFUL
|
||||
squares() / square of 2 -> SUCCESSFUL
|
||||
squares() / square of 3 -> SUCCESSFUL
|
||||
@@ -0,0 +1,7 @@
|
||||
--- no filter ---
|
||||
disabled() -> SKIPPED (waiting for the fix in ticket 1234)
|
||||
fast() -> SUCCESSFUL
|
||||
onlyWithProperty() -> SKIPPED (System property [lab.run.slow] does not exist)
|
||||
slow() -> SUCCESSFUL
|
||||
--- includeTags("fast") ---
|
||||
fast() -> SUCCESSFUL
|
||||
@@ -0,0 +1,2 @@
|
||||
inside the test : dir exists = true, files = 1
|
||||
after the test finished : dir exists = false
|
||||
@@ -0,0 +1,2 @@
|
||||
mock: next() -> 0, next() -> 0, real code ran 0 times
|
||||
spy : next() -> 1, next() -> 2, real code ran 2 times
|
||||
@@ -0,0 +1,3 @@
|
||||
when(spy.next()).thenReturn(100): real method ran while stubbing = 1 time(s)
|
||||
doReturn(100).when(spy).next() : real method ran while stubbing = 0 time(s)
|
||||
both return 100 and 100 after stubbing
|
||||
@@ -0,0 +1,14 @@
|
||||
times / atLeastOnce / never / inOrder: all passed
|
||||
--- verify(gw).lookup("zzz") ---
|
||||
Wanted but not invoked:
|
||||
paymentGateway.lookup("zzz");
|
||||
--- verify(gw).audit("declined c") ---
|
||||
Argument(s) are different! Wanted:
|
||||
paymentGateway.audit("declined c");
|
||||
-> at lab.jm.D_MockitoCoreTest.lambda$q20_verify$1(D_MockitoCoreTest.java:90)
|
||||
Actual invocations have different arguments:
|
||||
paymentGateway.charge("a", 500L);
|
||||
-> at lab.jm.OrderService.place(OrderService.java:17)
|
||||
--- verify(gw, never()).audit("declined b") ---
|
||||
paymentGateway.audit("declined b");
|
||||
Never wanted here:
|
||||
@@ -0,0 +1,5 @@
|
||||
when(gw.charge("a", anyLong())) -> InvalidUseOfMatchersException
|
||||
Invalid use of argument matchers!
|
||||
2 matchers expected, 1 recorded:
|
||||
-> at lab.jm.D_MockitoCoreTest.lambda$q21_matchersAndCaptor$0(D_MockitoCoreTest.java:103)
|
||||
ArgumentCaptor saw account=zoe cents=1234
|
||||
@@ -0,0 +1,11 @@
|
||||
MockitoExtension (default strictness):
|
||||
unusedStub() -> FAILED
|
||||
org.mockito.exceptions.misusing.UnnecessaryStubbingException
|
||||
|
||||
Unnecessary stubbings detected.
|
||||
Clean & maintainable test code requires zero unnecessary code.
|
||||
Following stubbings are unnecessary (click to navigate to relevant line of code):
|
||||
1. -> at lab.jm.fixtures.MockitoFixtures$StrictByDefault.unusedStub(MockitoFixtures.java:25)
|
||||
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
|
||||
@MockitoSettings(strictness = LENIENT):
|
||||
unusedStub() -> SUCCESSFUL
|
||||
@@ -0,0 +1,4 @@
|
||||
consecutive stubbing: true, false
|
||||
third call throws : gateway down
|
||||
void method via doThrow: audit store full
|
||||
thenAnswer / BDD willAnswer: lookup("7") = user-7
|
||||
@@ -0,0 +1,5 @@
|
||||
FinalPricer is final: true
|
||||
mock(FinalPricer.class).price(3) = 999 (real code would give 30)
|
||||
mock.getClass() == FinalPricer.class : true
|
||||
default MockMaker : org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
|
||||
class-file major version of org.mockito.Mockito : 55 (Java 11)
|
||||
@@ -0,0 +1,4 @@
|
||||
before : REAL-ID
|
||||
inside the scope : MOCK-ID
|
||||
other thread sees : REAL-ID
|
||||
after the scope : REAL-ID
|
||||
@@ -0,0 +1,4 @@
|
||||
before : RECEIPT[tea]
|
||||
inside : FAKE [tea]
|
||||
constructed during the scope: 1
|
||||
after : RECEIPT[tea]
|
||||
@@ -0,0 +1,5 @@
|
||||
Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
|
||||
WARNING: A Java agent has been loaded dynamically (~/.m2/repository/net/bytebuddy/byte-buddy-agent/1.17.7/byte-buddy-agent-1.17.7.jar)
|
||||
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
|
||||
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
|
||||
WARNING: Dynamic loading of agents will be disallowed by default in a future release
|
||||
@@ -0,0 +1,6 @@
|
||||
int -> 0
|
||||
boolean -> false
|
||||
String -> null
|
||||
List<String> -> []
|
||||
Optional<String> -> Optional.empty
|
||||
long -> 0
|
||||
@@ -0,0 +1,10 @@
|
||||
--- order a_, b_ (alphabetical) ---
|
||||
a_registersUser() -> SUCCESSFUL
|
||||
b_assumesUserExists() -> SUCCESSFUL
|
||||
--- order b_, a_ (reversed) ---
|
||||
b_assumesUserExists() -> FAILED
|
||||
a_registersUser() -> SUCCESSFUL
|
||||
AssertionFailedError: registry should contain the user registered by another test ==> expected: <1> but was: <0>
|
||||
--- time: the same code with an injected Clock ---
|
||||
acceptsOrders() at 10:00 UTC : true
|
||||
acceptsOrders() at 23:30 UTC : false
|
||||
@@ -0,0 +1,13 @@
|
||||
failsOnThirdRepetition(RepetitionInfo) / repetition 1 of 6 -> SUCCESSFUL
|
||||
failsOnThirdRepetition(RepetitionInfo) / repetition 2 of 6 -> SUCCESSFUL
|
||||
failsOnThirdRepetition(RepetitionInfo) / repetition 3 of 6 -> FAILED
|
||||
failsOnThirdRepetition(RepetitionInfo) / repetition 4 of 6 -> SKIPPED (Failure threshold [1] exceeded)
|
||||
failsOnThirdRepetition(RepetitionInfo) / repetition 5 of 6 -> SKIPPED (Failure threshold [1] exceeded)
|
||||
failsOnThirdRepetition(RepetitionInfo) / repetition 6 of 6 -> SKIPPED (Failure threshold [1] exceeded)
|
||||
withoutThreshold(RepetitionInfo) / repetition 1 of 6 -> SUCCESSFUL
|
||||
withoutThreshold(RepetitionInfo) / repetition 2 of 6 -> SUCCESSFUL
|
||||
withoutThreshold(RepetitionInfo) / repetition 3 of 6 -> FAILED
|
||||
withoutThreshold(RepetitionInfo) / repetition 4 of 6 -> SUCCESSFUL
|
||||
withoutThreshold(RepetitionInfo) / repetition 5 of 6 -> SUCCESSFUL
|
||||
withoutThreshold(RepetitionInfo) / repetition 6 of 6 -> SUCCESSFUL
|
||||
failed=2 skipped=3
|
||||
Reference in New Issue
Block a user