Unit Testing & MockK Quiz

TESTING › Unit

Which annotation pair correctly sets up a strict MockK mock and ensures it is initialized?

Answer: @MockK with MockKAnnotations.init(this)

MockK uses @MockK for a strict mock, and the fields must be initialized via MockKAnnotations.init(this) (often in @Before) or the MockK JUnit extension. @Mock/openMocks belong to Mockito.

You want a unit test where an unstubbed call to a collaborator returns a default value instead of throwing. What is the most direct MockK approach?

Answer: Create the mock with mockk(relaxed = true) from the start

A relaxed mock returns sensible defaults for any call you did not explicitly stub, so unstubbed calls do not throw. spyk runs real code, and confirmVerified only checks verification.

What is the idiomatic way to test a ViewModel function that calls a suspend repository method?

Answer: Use coEvery to stub and coVerify inside runTest

Suspend functions require MockK's coEvery/coVerify, executed inside runTest so coroutines run on the test scheduler. Plain every/verify cannot stub suspend calls, and JUnit test methods cannot be suspend.

According to Android's testing guidance, which test double should you generally prefer for a repository interface you own?

Answer: A hand-written fake with simple in-memory behavior

Google recommends fakes for collaborators you control: a fake has real, simplified behavior, making tests less brittle than interaction-heavy mocks that couple tests to implementation details.

Which JUnit annotation runs setup code before each individual @Test method?

Answer: @Before

@Before runs before every test method, giving each test a fresh fixture. @BeforeClass runs once for the whole class (and must be static), and @Setup is not a JUnit annotation.

You need to assert that the exact object passed into mock.save() has a specific field value. Which MockK feature fits best?

Answer: A slot<T>() with capture(), then read slot.captured

A CapturingSlot created with slot<T>() and wired via capture() records the actual argument, which you then inspect through slot.captured. The other options control ordering, sequential return values, or static mocking.

Which of these is the WEAKEST candidate for a JVM unit test?

Answer: A trivial getter returning its backing field unchanged

Trivial getters with no logic have no behavior of yours to verify, so a test just restates the implementation. Business logic, state transformations, and edge cases are exactly what unit tests should cover.

What distinguishes verifySequence from verifyOrder in MockK?

Answer: verifySequence is strict: only the listed calls in order, with no extras on the mock

verifySequence demands the exact set of calls in the given order with nothing else on the mock, while verifyOrder only checks the listed calls occurred in that relative order and tolerates other interleaved calls.

A ViewModel launches work in viewModelScope, which uses Dispatchers.Main. What lets this run in a plain JVM unit test?

Answer: Swap Main via Dispatchers.setMain, usually a MainDispatcherRule

Dispatchers.Main is not available on a bare JVM, so kotlinx-coroutines-test's Dispatchers.setMain (often wrapped in a MainDispatcherRule) swaps in a controllable test dispatcher. Sleeping or moving to androidTest defeats the point of a fast unit test.

You need a mocked method to return 1 on its first invocation and 2 on its second. Which MockK stub is correct?

Answer: every { m.next() } returns 1 andThen 2

Chaining returns with andThen supplies sequential results across successive calls (returnsMany also works). A second every block just overrides the first, and the other options return the wrong type rather than a sequence.

What does the @InjectMockKs annotation do in a MockK-based test?

Answer: It builds the class under test and injects the mock fields into it

@InjectMockKs builds the subject-under-test and injects the declared mock fields into its constructor or properties, so you do not assemble the object by hand. It still requires the mocks to be initialized first.

In a standard Android module, which source set holds fast JVM unit tests that need no device?

Answer: src/test

Local unit tests live in src/test and run on the host JVM. src/androidTest holds instrumented tests that require a device or emulator, and src/main and src/debug are production source sets.

What is the idiomatic Kotlin way to assert that calling a function throws IllegalArgumentException?

Answer: assertFailsWith<IllegalArgumentException> { subject.run() }

assertFailsWith<T> (or JUnit's assertThrows) runs the block, fails if no exception is thrown, fails if the wrong type is thrown, and returns the exception for further assertions. A bare try/catch can pass even when nothing throws.

You wrap a real object with spyk(RealService()) and never stub its foo() method. What happens when the test calls foo()?

Answer: It runs the real foo() implementation on the wrapped object

A spy delegates unstubbed calls to the real underlying object, so foo() runs for real while you can still stub or verify selected methods. A plain mockk would throw or, if relaxed, return defaults instead.

Back to Unit Testing & MockK