我目前正在尝试使用 JUnit5 和 Mockito 测试我的 Java Spring Boot 应用程序中的一个类。问题在于其中一个类方法使用了reactor netty HttpClient。我在嘲笑 httpclient 时遇到一些问题。我正在使用 webclient 模拟中的一个方法,其中我模拟了 httpclient 上的每个 scall。现在我收到以下错误:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
我的测试如下:
import io.netty.handler.codec.http.HttpMethod;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Spy;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufFlux;
import reactor.netty.ByteBufMono;
import reactor.netty.http.client.HttpClient;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
public class ServiceTest {
@Spy
private HttpClient httpClient;
@Mock
HttpClient.RequestSender requestSender;
@Mock
ByteBufFlux byteBufFlux;
@Mock
ByteBufMono byteBufMono;
@BeforeEach
void setup() {
httpClient = HttpClient.create();
}
@Test
void testFetchImageFromURLBase64Success() {
mockStatic( HttpClient.class );
mockHttpClient();
var host = "example.com";
var port = 80;
var imageUrl = "http://example.com/image.jpg";
when( httpClient.request( HttpMethod.GET ) )
.thenReturn( requestSender );
var res = Service.fetchImageFromURLBase64( host, port, imageUrl );
assertNotNull( res );
}
private void mockHttpClient() {
var mockImageBytes = new byte[]{ (byte)0x89, (byte)0x50 };
when( httpClient.request( HttpMethod.GET ) )
.thenReturn( requestSender );
when( requestSender.uri( anyString() ) )
.thenReturn( requestSender );
when( requestSender.responseContent() )
.thenReturn( byteBufFlux );
when( byteBufFlux.aggregate() )
.thenReturn( byteBufMono );
when( byteBufMono.asByteArray() )
.thenReturn( Mono.just( mockImageBytes ) );
}
}
我想测试使用 httpclient 的方法如下所示:
public static String fetchImageFromURLBase64( String hostName, int port, String imageUrl ) {
try {
var httpClient = HttpClient.create()
.proxy( p -> p.type( ProxyProvider.Proxy.HTTP ).host( hostName ).port( port ) );
var response = httpClient
.request( HttpMethod.GET )
.uri( imageUrl )
.responseContent()
.aggregate()
.asByteArray()
.block();
if( response == null || response.length == 0 ) {
log.error( "Could not retrieve image bytes from url: {}", imageUrl );
return null;
}
return Base64.getEncoder().encodeToString( response );
} catch( Exception e ) {
// In case the service returns a 500 we don't want the application to crash
log.error( "Error retrieving image from URL: {} with error message: ", imageUrl, e );
return null;
}
}
有人知道为什么我会收到一般错误吗?或者是否有更好/更简单的方法来模拟 httpclient 调用?
您的
@Spy
注释无用,原因有两个:
假设您已加载 Mockito 扩展:
@ExtendWith(MockitoExtension.class)
public class ServiceTest {
@Spy
private HttpClient httpClient;
@BeforeEach
void setup() {
httpClient = HttpClient.create();
}
@Test
void test() {
// …
}
}
那么当你的测试执行时会发生什么?
ServiceTest
的新实例httpClient
字段被赋值为创建的Spy对象HttpClient.create()
更详细的解释和问题的几种解决方案可以在为什么在执行单元测试时没有调用我的模拟方法?