如何使用 Mockito 模拟 Java 中的泛型方法?

How to mock generic method in Java with Mockito?

我们如何模拟 IRouteHandlerRegistry?错误是 Cannot resolve method thenReturn(IHandleRoute<TestRoute>)

public interface RouteDefinition { }

public class TestRoute implements RouteDefinition { }

public interface IHandleRoute<TRoute extends RouteDefinition> {
    Route getHandlerFor(TRoute route);
}

public interface IRouteHandlerRegistry {
    <TRoute extends RouteDefinition> IHandleRoute<TRoute> getHandlerFor(TRoute route);
}

@Test
@SuppressWarnings("unchecked")
public void test() {
    // in my test
    RouteDefinition route = new TestRoute(); // TestRoute implements RouteDefinition
    IRouteHandlerRegistry registry = mock(IRouteHandlerRegistry.class);
    IHandleRoute<TestRoute> handler = mock(IHandleRoute.class);

    // Error: Cannot resolve method 'thenReturn(IHandleRoute<TestRoute>)'
    when(registry.getHandlerFor(route)).thenReturn(handler);
}

这样写就ok了:

Mockito.doReturn(handler).when(registry).getHandlerFor(Mockito.any(route.class))

Mockito.when 参数应该是方法而不是模拟。

正确的说法是: when(registry.getHandlerFor (route)).thenReturn(handler)

尽管 TestRouteRouteDefinition 的子类型,但 IHandleRoute<TestRoute> 而不是 IHandleRoute<RouteDefinition> 的子类型。

来自 Mockito 的 when 方法 returns 类型 OngoingStubbing<IHandleRoute<RouteDefinition>> 的对象。这是由于编译器从方法

中推断出类型参数 TRoute
<TRoute extends RouteDefinition> IHandleRoute<TRoute> getHandlerFor(TRoute route);

RouteDefinition 因为传递给 getHandlerFor 的参数被声明为 RouteDefinition.

类型

另一方面,thenReturn 方法被赋予了一个 IHandleRoute<TestRoute> 类型的参数,而它期望一个 IHandleRoute<RouteDefinition>,即 OngoingStubbing 的类型参数较早前提过。因此编译器错误。

要解决这个问题,最简单的方法可能是将 route 的声明类型更改为 TestRoute:

TestRoute route = new TestRoute();

IRouteHandlerRegistry registry = mock(IRouteHandlerRegistry.class);
IHandleRoute<TestRoute> handler = mock(IHandleRoute.class);

when(registry.getHandlerFor(route)).thenReturn(handler);