Tim*_*ons 261 java generics mockito
是否有一种使用泛型参数模拟类的干净方法?假设我必须模拟一个Foo<T>我需要传递给期望a的方法的类Foo<Bar>.我可以很容易地做到以下几点:
Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
Run Code Online (Sandbox Code Playgroud)
假设getValue()返回泛型类型T.但是当我稍后将它传递给期望的方法时,那将会有小猫Foo<Bar>.铸造是这样做的唯一方法吗?
小智 261
另一种方法是使用@Mock注释.在所有情况下都不起作用,但看起来更性感:)
这是一个例子:
@RunWith(MockitoJUnitRunner.class)
public class FooTests {
@Mock
public Foo<Bar> fooMock;
@Test
public void testFoo() {
when(fooMock.getValue()).thenReturn(new Bar());
}
}
Run Code Online (Sandbox Code Playgroud)
在MockitoJUnitRunner初始化带注释的字段@Mock.
Joh*_*ett 253
我认为你确实需要施展它,但它不应该太糟糕:
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue()).thenReturn(new Bar());
Run Code Online (Sandbox Code Playgroud)
dsi*_*ton 35
您始终可以创建一个中间类/接口,以满足您要指定的泛型类型.例如,如果Foo是一个接口,您可以在测试类中创建以下接口.
private interface FooBar extends Foo<Bar>
{
}
Run Code Online (Sandbox Code Playgroud)
在Foo 是非final类的情况下,您可以使用以下代码扩展该类并执行相同的操作:
public class FooBar extends Foo<Bar>
{
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用以下代码使用上述任一示例:
Foo<Bar> mockFoo = mock(FooBar.class);
when(mockFoo.getValue()).thenReturn(new Bar());
Run Code Online (Sandbox Code Playgroud)
acd*_*ior 15
创建测试实用程序方法.如果你不止一次需要它特别有用.
@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);
}
Run Code Online (Sandbox Code Playgroud)
Tob*_*ann 11
我同意不应抑制类或方法中的警告,因为人们可能会忽略其他意外抑制的警告。但恕我直言,抑制仅影响一行代码的警告是绝对合理的。
@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
Run Code Online (Sandbox Code Playgroud)
vog*_*lla 11
对于 JUnit5,我认为最好的方法是在方法参数或字段中使用 @ExtendWith(MockitoExtension.class) 和 @Mock。
以下示例通过 Hamcrest 匹配器演示了这一点。
package com.vogella.junit5;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.mockito.Mockito.verify;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class MockitoArgumentCaptureTest {
@Captor
private ArgumentCaptor<List<String>> captor;
@Test
public final void shouldContainCertainListItem(@Mock List<String> mockedList) {
var asList = Arrays.asList("someElement_test", "someElement");
mockedList.addAll(asList);
verify(mockedList).addAll(captor.capture());
List<String> capturedArgument = captor.getValue();
assertThat(capturedArgument, hasItem("someElement"));
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅https://www.vogella.com/tutorials/Mockito/article.html了解所需的 Maven/Gradle 依赖项。
正如其他答案所提到的,在没有不安全的泛型访问和/或抑制泛型警告的情况下,没有一种直接使用mock()&spy()方法的好方法。
Mockito 项目 ( #1531 ) 中目前存在一个未解决的问题,以添加对使用mock()&spy()方法的支持,而没有泛型警告。该问题于 2018 年 11 月开放,但没有任何迹象表明它会被优先考虑。根据 Mockito 贡献者对该问题的评论之一:
鉴于
.class泛型不能很好地发挥作用,我认为我们在 Mockito 中没有任何解决方案。您已经可以做到@Mock(JUnit5 扩展也允许方法参数@Mock),这应该是一个合适的替代方案。因此,我们可以保持这个问题开放,但它不太可能被修复,因为这@Mock是一个更好的 API。
所以你有这个:
Foo mockFoo = mock(Foo.class);
Run Code Online (Sandbox Code Playgroud)
@SuppressWarnings("unchecked")注释。并不能真正解决问题,但您将不再收到警告。@SuppressWarnings("unchecked")
Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
Run Code Online (Sandbox Code Playgroud)
@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());
Run Code Online (Sandbox Code Playgroud)
when实际测试时可以添加。@Mock
public Foo<Bar> fooMock;
Run Code Online (Sandbox Code Playgroud)
@MockBean
public Foo<Bar> fooMock;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
152255 次 |
| 最近记录: |