如何从通用通配符中模拟 return
How can I mock the return from a generic wildcard
我正试图了解 java 8 中的泛型和通配符。但我不明白为什么不能模拟此存储库方法。
代码非常简单,因此应该很容易重现。
我在 "when"
的 "thenReturn" 部分遇到了这个编译错误
The method thenReturn(Stream<capture#1-of ? extends Something>) in the type
OngoingStubbing<Stream<capture#1-of ? extends Something>> is not applicable
for the arguments (Stream<capture#3-of ? extends Something>)
测试:
@Test
public void ItShourReturnStreamFromRepository() {
List<Something> list = new ArrayList<Something>();
list.add(new Something());
Stream<? extends Something> stream = list.stream();
when(someRepository.getStream()).thenReturn(stream);
}
class:
public class Something {}
存储库:
public interface SomeRepository{
Stream<? extends Something> getStream();
}
有人可以帮忙吗?
谢谢!
这是通配符类型的普遍问题。用一个简化的、独立于 Mockito 的例子来演示它:
Enum<?> e = Thread.State.BLOCKED;
// produces "incompatible types: Enum<CAP#1> cannot be converted to Enum<CAP#2>"
Arrays.asList(e).set(0, e);
// works since Java 8
List<Enum<?>> list=Arrays.asList(e);
list.add(e);
// works even in older versions
Arrays.<Enum<?>>asList(e).set(0, e);
这为您指出了应该也适用于 Mockito API 的可能解决方案。但是,要设计像 SomeRepository
这样的 API,您应该遵循一般的 “Guidelines for Wildcard Use”:
Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.
Stream 的元素类型中的 ? extends
产生了一个没有任何好处的复杂化。您始终可以创建 Stream<Something>
,甚至可以从具有更具体类型的源创建,例如
SubTypeOfSomething subTyped = …
// from specific values
Stream<Something> s1 = Stream.of(subTyped);
// from existing collection
Set<SubTypeOfSomething> set = Collections.singleton(subTyped);
// note: this creates the stream directly from the source set
Stream<Something> s2 = Collections.<Something>unmodifiableSet(set).stream();
// if you really unavoidably have a more specifically typed Stream
Stream<SubTypeOfSomething> s3 = set.stream();
Stream<Something> s4 = s3.map(Function.identity());
Stream<? extends Something>
不提供任何 Stream<Something>
不提供的东西。
如果接口是键入的,那将是另一回事,例如 :
interface SomeRepository<T extends Something> {
Stream<T> getStream();
}
那么,您就没有通配符了,更具体类型的流可能会有所帮助。
先不考虑使用 return 类型和通配符是好是坏的问题,这个问题可以通过 Mockito 通过 doReturn().when()
而不是 [=12= 来模拟来解决]. doReturn()
模式不是类型安全的,因此建议仅在没有更好的选择时才使用它(如本例)。这样,您的测试可以写成:
@Test
public void ItShourReturnStreamFromRepository() {
List<Something> list = new ArrayList<Something>();
list.add(new Something());
Stream<? extends Something> stream = list.stream();
doReturn(stream).when(someRepository).getStream();
}
我正试图了解 java 8 中的泛型和通配符。但我不明白为什么不能模拟此存储库方法。 代码非常简单,因此应该很容易重现。
我在 "when"
的 "thenReturn" 部分遇到了这个编译错误The method thenReturn(Stream<capture#1-of ? extends Something>) in the type
OngoingStubbing<Stream<capture#1-of ? extends Something>> is not applicable
for the arguments (Stream<capture#3-of ? extends Something>)
测试:
@Test
public void ItShourReturnStreamFromRepository() {
List<Something> list = new ArrayList<Something>();
list.add(new Something());
Stream<? extends Something> stream = list.stream();
when(someRepository.getStream()).thenReturn(stream);
}
class:
public class Something {}
存储库:
public interface SomeRepository{
Stream<? extends Something> getStream();
}
有人可以帮忙吗? 谢谢!
这是通配符类型的普遍问题。用一个简化的、独立于 Mockito 的例子来演示它:
Enum<?> e = Thread.State.BLOCKED;
// produces "incompatible types: Enum<CAP#1> cannot be converted to Enum<CAP#2>"
Arrays.asList(e).set(0, e);
// works since Java 8
List<Enum<?>> list=Arrays.asList(e);
list.add(e);
// works even in older versions
Arrays.<Enum<?>>asList(e).set(0, e);
这为您指出了应该也适用于 Mockito API 的可能解决方案。但是,要设计像 SomeRepository
这样的 API,您应该遵循一般的 “Guidelines for Wildcard Use”:
Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.
Stream 的元素类型中的 ? extends
产生了一个没有任何好处的复杂化。您始终可以创建 Stream<Something>
,甚至可以从具有更具体类型的源创建,例如
SubTypeOfSomething subTyped = …
// from specific values
Stream<Something> s1 = Stream.of(subTyped);
// from existing collection
Set<SubTypeOfSomething> set = Collections.singleton(subTyped);
// note: this creates the stream directly from the source set
Stream<Something> s2 = Collections.<Something>unmodifiableSet(set).stream();
// if you really unavoidably have a more specifically typed Stream
Stream<SubTypeOfSomething> s3 = set.stream();
Stream<Something> s4 = s3.map(Function.identity());
Stream<? extends Something>
不提供任何 Stream<Something>
不提供的东西。
如果接口是键入的,那将是另一回事,例如
interface SomeRepository<T extends Something> {
Stream<T> getStream();
}
那么,您就没有通配符了,更具体类型的流可能会有所帮助。
先不考虑使用 return 类型和通配符是好是坏的问题,这个问题可以通过 Mockito 通过 doReturn().when()
而不是 [=12= 来模拟来解决]. doReturn()
模式不是类型安全的,因此建议仅在没有更好的选择时才使用它(如本例)。这样,您的测试可以写成:
@Test
public void ItShourReturnStreamFromRepository() {
List<Something> list = new ArrayList<Something>();
list.add(new Something());
Stream<? extends Something> stream = list.stream();
doReturn(stream).when(someRepository).getStream();
}