Resolving Mockito when() Method Invocation Exception: Calls Must Be on Mock Objects

Dec 01, 2025 · Programming · 27 views · 7.8

Keywords: Mockito | unit testing | mock objects

Abstract: This article provides an in-depth analysis of the common MissingMethodInvocationException in Mockito during unit testing. The exception occurs when the argument to when() is not a method call on a mock object. Through code examples, it explores root causes and offers three solutions: proper mock creation, avoiding stubbing of final/private methods, and handling open methods in Kotlin. These approaches help developers quickly diagnose and fix mocking issues, enhancing code quality and test efficiency.

Problem Background and Exception Analysis

When using the Mockito framework for unit testing, developers often encounter the org.mockito.exceptions.misusing.MissingMethodInvocationException. The core message states that the when() method requires an argument that must be "a method call on a mock." For example, correct usage is when(mock.getArticles()).thenReturn(articles);, where mock is a mock object and getArticles() is a method call on it.

The exception can arise from two main causes: first, attempting to stub final, private, equals(), or hashCode() methods, which cannot be stubbed or verified in Mockito. Second, the method call inside when() is not on a mock object but on some other object, often due to improper mock initialization.

Solution 1: Proper Mock Object Creation

As per the best answer, the primary solution is to ensure correct mock object creation. In the given example, the exception stems from stubbing pcUserService.read("1") without properly mocking pcUserService. The correct approach is to explicitly create a mock using Mockito's mock() method.

Here is a corrected code example:

// Create a mock object of PcUserService
PcUserService mockService = org.mockito.Mockito.mock(PcUserService.class);
// Call the method on the mock and stub it
when(mockService.read("1")).thenReturn(pcUser);

This ensures that the argument to when(), mockService.read("1"), is indeed a method call on a mock object, preventing the exception. This method is applicable in most Java scenarios, especially when integrated with the Spring Test framework, ensuring test isolation and repeatability.

Solution 2: Avoiding Stubbing of Final or Private Methods

The second answer highlights that if the method being stubbed is declared as final, it can also cause this exception. Mockito, in its default configuration, cannot mock final methods because the Java final keyword prevents method overriding, and Mockito relies on dynamic proxies or bytecode manipulation to create mocks.

For instance, if the read method in PcUserService is defined as final:

public final PcUser read(String id) {
    // method implementation
}

In this case, even with a properly created mock, Mockito cannot intercept calls to the read method, leading to the exception. Solutions include avoiding stubbing of final methods or using Mockito extensions (e.g., inline mock maker in Mockito 2+) to support final method mocking. However, better practice is to redesign code to reduce reliance on final methods, improving testability.

Solution 3: Special Handling in Kotlin

The third answer provides additional insight for Kotlin. In Kotlin, all methods are final by default unless explicitly declared with the open keyword. Therefore, if the class under test is written in Kotlin and its methods need to be mocked, they must be marked as open.

For example, in Kotlin:

// Incorrect: methods are final by default, cannot be mocked by Mockito
class PcUserService {
    fun read(id: String): PcUser {
        // implementation
    }
}

// Correct: use open keyword to allow mocking
open class PcUserService {
    open fun read(id: String): PcUser {
        // implementation
    }
}

By declaring methods as open, Mockito can successfully create mock objects and intercept method calls, avoiding the exception. This is particularly important for teams using Kotlin, requiring consideration in coding standards early on.

Summary and Best Practices

The key to resolving the when() method invocation exception in Mockito lies in understanding how mock objects work. First, always ensure that the target object is properly mocked before calling when(). Second, avoid stubbing final, private, or special methods like equals and hashCode, as these typically don't need mocking in unit tests. Finally, in Kotlin projects, be aware of the default final nature of methods and use the open keyword to support mocking.

By following these practices, developers can write unit tests more efficiently, reduce debugging time, and improve code reliability. Mockito, as a widely used mocking framework in the Java ecosystem, is essential for maintaining high-quality software when used correctly.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.