如何在 quarkus 中使用mockito模拟实例类?
最初我有一个最小的可重现代码,其工作原理如下:
我有一个由 ServiceA 类实现的接口:
public interface ServiceInterface {
public String getName();
}
@ApplicationScoped
public class ServiceA implements ServiceInterface {
@Override
public String getName() {
return "I am A";
}
}
这已被资源使用:
@Path("/hello")
public class GreetingResource {
@Inject
ServiceInterface service;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(service.getName());
return stringBuilder.toString();
}
}
按预期工作:
我可以编写一个简单的测试来模拟它(
quarkus-junit5-mockito
添加到pom.xml
):
import static org.mockito.Mockito.when;
@QuarkusTest
class GreetingResourceTest {
@InjectMock
ServiceInterface service;
@Test
void testHelloEndpoint() {
when(service.getName()).thenReturn("I am C");
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("I am C"));
}
}
现在我介绍第二项服务:
@ApplicationScoped
public class ServiceB implements ServiceInterface {
@Override
public String getName() {
return "I am B";
}
}
我更改了我的资源以接受这两项服务:
Instance
:
@Path("/hello")
public class GreetingResource {
@Inject
Instance<ServiceInterface> services;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
StringBuilder stringBuilder = new StringBuilder();
for (ServiceInterface service : services) {
stringBuilder.append(service.getName());
}
return stringBuilder.toString();
}
}
但是我无法找到重写我的测试的方法。
@QuarkusTest
class GreetingResourceTest {
@InjectMock
Instance<ServiceInterface> services;
@Test
void testHelloEndpoint() {
// This is wrong!!!
when(services.get().getName()).thenReturn("I am C");
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("I am C"));
}
}
@QuarkusTest
class GreetingResourceTest {
@Mock
Instance<ServiceInterface> services;
@InjectMock
ServiceInterface service;
@Test
void testHelloEndpoint() {
// This is wrong!!
when(services.get()).thenReturn(service);
when(services.get().getName()).thenReturn("I am C");
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("I am C"));
}
}
但我无法从返回的异常中找到任何有意义的东西,例如:
org.acme.GreetingResourceTest 类的字段 jakarta.enterprise.inject.Instance
org.acme.GreetingResourceTest.services 不是生产者字段,但使用构造型注释:io.quarkus.test.Mock
我想你想要类似下面的东西。我没有使用过 Quarkus,所以我在这里做了一些假设(包括
Instance::get
返回 List
),但想法是您想要向被测试的类提供 Instance<ServiceInterface>
,并模拟其get()
方法,然后返回一个模拟 ServiceInterface
,您已在其中设置了适当的期望(或者您甚至可以返回其中一项服务的实际实例)。
@QuarkusTest
class GreetingResourceTest {
@InjectMock
Instance<ServiceInterface> services;
@Mock
ServiceInterface service;
@Test
void testHelloEndpoint() {
when(services.get()).thenReturn(List.of(service));
when(service.getName()).thenReturn("I am C");
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("I am C"));
}
}
对于后一种情况,您只需返回服务的实际实例:
when(services.get()).thenReturn(List.of(new ServiceB()));