使用 Mockito 模拟具有泛型参数的类
题
是否有一种干净的方法来模拟带有泛型参数的类?假设我必须模拟一堂课 Foo<T>
我需要将其传递给一个需要的方法 Foo<Bar>
. 。我可以很容易地做到以下几点:
Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
假设 getValue()
返回泛型类型 T
. 。但是当我稍后将它传递给期望的方法时,将会有小猫 Foo<Bar>
. 。铸造是做到这一点的唯一手段吗?
解决方案
我想你需要转换它,但它不应该是太糟糕了:
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
其他提示
另一种解决方法是使用 @Mock
改为注释。并非在所有情况下都有效,但看起来更性感:)
这是一个例子:
@RunWith(MockitoJUnitRunner.class)
public class FooTests {
@Mock
public Foo<Bar> fooMock;
@Test
public void testFoo() {
when(fooMock.getValue()).thenReturn(new Bar());
}
}
这 MockitoJUnitRunner
初始化带有注释的字段 @Mock
.
您总是可以创建一个中间类/接口,将满足您想要指定泛型类型。例如,如果富是一个界面,你可以在你的测试类创建以下界面。
private interface FooBar extends Foo<Bar>
{
}
在情况下美孚是非最终类,你可以只用下面的代码扩展类和做同样的事情:
public class FooBar extends Foo<Bar>
{
}
然后,你可以用下面的代码消耗上述任一例子:
Foo<Bar> mockFoo = mock(FooBar.class);
when(mockFoo.getValue()).thenReturn(new Bar());
创建测试工具方法。如果你需要它不止一次特别有用。
@Test
public void testMyTest() {
// ...
Foo<Bar> mockFooBar = mockFoo();
when(mockFooBar.getValue).thenReturn(new Bar());
Foo<Baz> mockFooBaz = mockFoo();
when(mockFooBaz.getValue).thenReturn(new Baz());
Foo<Qux> mockFooQux = mockFoo();
when(mockFooQux.getValue).thenReturn(new Qux());
// ...
}
@SuppressWarnings("unchecked") // still needed :( but just once :)
private <T> Foo<T> mockFoo() {
return mock(Foo.class);
}
下面是一个有趣的例子:方法receieves通用集合,并返回相同的基本类型的通用集合。例如:
Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);
此方法可以与anyCollectionOf的Mockito匹配和应答的组合被模拟。
when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
new Answer<Collection<Assertion>>() {
@Override
public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
return new ArrayList<Assertion>();
}
});
我同意不应该抑制类或方法的警告作为一个可以忽略其他,意外地抑制警告。但恕我直言这是绝对合理的抑制将只影响一个单一的代码行的警告。
@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
不隶属于 StackOverflow