Java 使用 Mockito 模拟具有泛型参数的类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1652692/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 18:41:37  来源:igfitidea点击:

Using Mockito to mock classes with generic parameters

javagenericsmockito

提问by Tim Clemons

Is there a clean method of mocking a class with generic parameters? Say I have to mock a class Foo<T>which I need to pass into a method that expects a Foo<Bar>. I can do the following easily enough:

是否有一种干净的方法来模拟具有泛型参数的类?假设我必须模拟一个类Foo<T>,我需要将它传递给一个需要Foo<Bar>. 我可以很容易地做到以下几点:

Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());

Assuming getValue()returns the generic type T. But that's going to have kittens when I later pass it into a method expecting Foo<Bar>. Is casting the only means of doing this?

假设getValue()返回泛型类型T。但是当我稍后将它传递给一个期望Foo<Bar>. 铸造是这样做的唯一方法吗?

采纳答案by John Paulett

I think you do need to cast it, but it shouldn't be too bad:

我认为您确实需要投射它,但应该不会太糟糕:

Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue()).thenReturn(new Bar());

回答by Marek Kirejczyk

One other way around this is to use @Mockannotation instead. Doesn't work in all cases, but looks much sexier :)

解决此问题的另一种方法是使用@Mock注释。并非在所有情况下都有效,但看起来更性感 :)

Here's an example:

下面是一个例子:

@RunWith(MockitoJUnitRunner.class)
public class FooTests {

    @Mock
    public Foo<Bar> fooMock;

    @Test
    public void testFoo() {
        when(fooMock.getValue()).thenReturn(new Bar());
    }
}

The MockitoJUnitRunnerinitializes the fields annotated with @Mock.

MockitoJUnitRunner初始化带注释的字段@Mock

回答by dsingleton

You could always create an intermediate class/interface that would satisfy the generic type that you are wanting to specify. For example, if Foo was an interface, you could create the following interface in your test class.

您始终可以创建一个满足您要指定的泛型类型的中间类/接口。例如,如果 Foo 是一个接口,您可以在您的测试类中创建以下接口。

private interface FooBar extends Foo<Bar>
{
}

In situations where Foo is a non-finalclass, you could just extend the class with the following code and do the same thing:

在 Foo是非 final类的情况下,您可以使用以下代码扩展该类并执行相同的操作:

public class FooBar extends Foo<Bar>
{
}

Then you could consume either of the above examples with the following code:

然后,您可以使用以下代码使用上述任一示例:

Foo<Bar> mockFoo = mock(FooBar.class);
when(mockFoo.getValue()).thenReturn(new Bar());

回答by qza

Here is an interesting case: method receieves generic collection and returns generic collection of same base type. For example:

这是一个有趣的案例:方法接收泛型集合并返回相同基类型的泛型集合。例如:

Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);

This method can be mocked with combination of Mockito anyCollectionOf matcher and the Answer.

可以通过 Mockito anyCollectionOf 匹配器和 Answer 的组合来模拟此方法。

when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
     new Answer<Collection<Assertion>>() {
         @Override
         public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
             return new ArrayList<Assertion>();
         }
     });

回答by acdcjunior

Create a test utility method. Specially useful if you need it for more than once.

创建一个测试实用程序方法。如果您多次需要它,则特别有用。

@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);
}

回答by Tobias Uhmann

I agree that one shouldn't suppress warnings in classes or methods as one could overlook other, accidentally suppressed warnings. But IMHO it's absolutely reasonable to suppress a warning that affects only a single line of code.

我同意不应抑制类或方法中的警告,因为人们可能会忽略其他意外抑制的警告。但恕我直言,抑制仅影响一行代码的警告是绝对合理的。

@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);