Mockito 2的模拟返回流 – 没有找到合适的方法

huangapple go评论57阅读模式
英文:

Mockito 2 Mocks Returning Stream - No suitable method found

问题

以下是翻译好的内容:

我在实现中有一个带有以下签名的函数:

Class Foo {
    Stream<? extends Bar> doSomething() { ... }
}

然而,在我的测试中,当我进行如下操作时:

when(foo.doSomething()).thenReturn(Stream.of(bar1, bar2));

我遇到了以下编译错误:

没有找到适合的 thenReturn(java.util.stream.Stream<Bar>) 方法
方法 org.mockito.stubbing.OngoingStubbing.thenReturn(java.util.stream.Stream<capture#1 of ? extends Bar>,java.util.stream.Stream<capture#1 of ? extends Bar>...) 不适用
      参数不匹配推断变量 T 具有不兼容的界限
        相等约束capture#1 of ? extends Bar
          下界Bar

不幸的是,使用 Stream.<? extends Foo>(bar1, bar2) 也不起作用。正在寻找解决方法。

谢谢!


编辑:
值得注意的是,当我使用 Mockito 1.10.x 时,这是可行的,但一旦我更新到 Mockito 2.28.x,它就不起作用了。

英文:

I have a function in the implementation with the signature

Class Foo {
    Stream&lt;? extends Bar&gt; doSomething() { ... }
}

However, in my tests when I did something like

when(foo.doSomething()).thenReturn(Stream.of(bar1, bar2));

I got the following compilation error:

no suitable method found for thenReturn(java.util.stream.Stream&lt;Bar&gt;)
method org.mockito.stubbing.OngoingStubbing.thenReturn(java.util.stream.Stream&lt;capture#1 of ? extends Bar&gt;,java.util.stream.Stream&lt;capture#1 of ? extends Bar&gt;...) is not applicable
      (argument mismatch; inference variable T has incompatible bounds
        equality constraints: capture#1 of ? extends Bar
          lower bounds: Bar)

Unfortunately, using Stream.&lt;? extends Foo&gt;(bar1, bar2) didn't work either. Looking for a fix.

Thanks!


EDIT:
FYI this worked when I was using Mockito 1.10.x, it stopped working once i updated Mockito to 2.28.x

答案1

得分: 1

Solution

唯一可行的解决方法是使用 OngoingStubbing&lt;T&gt; thenAnswer(Answer&lt;?&gt; answer),它期望任何参数化类型 (Answer&lt;?&gt;):

  • 扩展的代码:

    Stream&lt;? extends Bar&gt; stream = Stream.of(new Buzz(), new Buzz(), new Buzz());
    
    Mockito.when(foo.doSomething()).thenAnswer(new Answer&lt;Stream&lt;? extends Bar&gt;&gt;() {
        @Override
        public Stream&lt;? extends Bar&gt; answer(InvocationOnMock invocation) {
            return stream;
        }
    });
    
  • 简化版本:

    Mockito.when(foo.doSomething()).thenAnswer(invocation -> stream);

Explanation

OngoingStubbing&lt;T&gt; thenReturn(T value) 方法在模拟 Stream&lt;? extends Bar&gt; doSomething() 方法时,期望输入是 Stream&lt;? extends Bar&gt; 类型。传递 Stream.of(bar1, bar2)) 不能保证参数与相同的参数化类型匹配。

Buzz 扩展 Bar

Stream&lt;? extends Bar&gt; stream = Stream.of(new Buzz(), new Buzz(), new Buzz());
Mockito.when(foo.doSomething()).thenReturn(stream);

完全相同的问题也可以在以下代码中重现:

static class FluentFactory {
    static &lt;T&gt; Fluent&lt;T&gt; fluent(T methodCall) { return new Fluent&lt;&gt;(); }
}
    
static class Fluent&lt;T&gt;  {
    Fluent&lt;T&gt; first(T t) { return new Fluent&lt;&gt;(); }
}
Stream&lt;? extends Bar&gt; stream = Stream.of(new Buzz(), new Buzz(), new Buzz());
FluentFactory.fluent(foo.doSomething()).first(stream);

错误:(xx, yy) java: 不兼容的类型: java.util.stream.Stream<capture#1 of ? extends com.mycompany.Foo> 无法转换为 java.util.stream.Stream<capture#2 of ? extends com.mycompany.Foo>

英文:

Solution

The only possible workaround is using OngoingStubbing&lt;T&gt; thenAnswer(Answer&lt;?&gt; answer) which expects any parametrized type (Answer&lt;?&gt;):

  • expanded:

    Stream&lt;? extends Bar&gt; stream = Stream.of(new Buzz(), new Buzz(), new Buzz());
    
    Mockito.when(foo.doSomething()).thenAnswer(new Answer&lt;Stream&lt;? extends Bar&gt;&gt;() {
        @Override
        public Stream&lt;? extends Bar&gt; answer(InvocationOnMock invocation) {
            return stream;
        }
    });
    
  • short version:

    Mockito.when(foo.doSomething()).thenAnswer(invocation -&gt; stream);
    

Explanation

The method OngoingStubbing&lt;T&gt; thenReturn(T value) expects in case of mocking Stream&lt;? extends Bar&gt; doSomething() method the Stream&lt;? extends Bar&gt; type at the input. Passing Stream.of(bar1, bar2)) doesn't guarantee the parameters fit the same parametrized type.

Let Buzz extend Bar:

Stream&lt;? extends Bar&gt; stream = Stream.of(new Buzz(), new Buzz(), new Buzz());
Mockito.when(foo.doSomething()).thenReturn(stream);

The very same issue is reproducible with the following code:

static class FluentFactory {
    static &lt;T&gt; Fluent&lt;T&gt; fluent(T methodCall) { return new Fluent&lt;&gt;(); }
}
    
static class Fluent&lt;T&gt;  {
    Fluent&lt;T&gt; first(T t) { return new Fluent&lt;&gt;(); }
}
Stream&lt;? extends Bar&gt; stream = Stream.of(new Buzz(), new Buzz(), new Buzz());
FluentFactory.fluent(foo.doSomething()).first(stream);

> Error:(xx, yy) java: incompatible types: java.util.stream.Stream<capture#1 of ? extends com.mycompany.Foo> cannot be converted to java.util.stream.Stream<capture#2 of ? extends com.mycompany.Foo>

答案2

得分: 0

一个解决方法是使用:

when(fooMock.doSomething())
        .thenAnswer((Answer&lt;Stream&lt;? extends Bar&gt;&gt;) invocation -&gt; Stream.of(bar1, bar2));

这不会导致编译或运行时错误。

英文:

A workaround to this, use:

when(fooMock.doSomething())
        .thenAnswer((Answer&lt;Stream&lt;? extends Bar&gt;&gt;) invocation -&gt; Stream.of(bar1, bar2));

This causes no compilation or runtime error.

huangapple
  • 本文由 发表于 2020年9月23日 05:34:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/64017977.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定