如何使用 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)
尽管 TestRoute
是 RouteDefinition
的子类型,但 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);
我们如何模拟 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)
尽管 TestRoute
是 RouteDefinition
的子类型,但 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);