在 Helidon 测试中用模拟替换 bean
Replace a bean by a mock in Helidon test
我有一个 Helidon 应用程序,我想测试它的(部分)。
我的测试用 @HelidonTest
注释,现在我想用一个 mock 替换一个 bean(并配置这个 mock,使用找到的所有其他 bean,但注入 mock)。
我确实想出了如何:
- 用测试实现替换一个 bean(单独 class):通过用
@Priority(1)
和 @Alternative
注释测试实现 class 并通过注释测试提供它@AddBean(MyBeanTestImpl.class)
。
- 但我无法创建一个模拟(使用 Mockito)作为个人 class。
- 产生一个
mock(MyBean.class)
:通过创建一个生产者方法并用@Produces
注释它:
- 但它与真正的 bean 冲突并给出:“WELD-001409:类型的不明确依赖性...”
- 当我也用
@Alternative
注释它时,它会被忽略。
- 我不能用
@Priority(1)
注解,因为这个注解只能应用于类型和参数。
知道如何用模拟替换一个 bean 吗?
我尝试了 setter 注入来手动注入模拟 bean。
Class 测试中
@ApplicationScoped
public class SomeService {
private ExternalService externalService;
@Inject
public void setExternalService(ExternalService externalService) {
this.externalService = externalService;
}
public String doSomething() {
return externalService.getData();
}
}
测试Class
@HelidonTest
class SomeServiceTest {
@Inject
private SomeService someService;
private ExternalService externalService;
@BeforeEach
void setUp() {
externalService = Mockito.mock(ExternalService.class);
someService.setExternalService(externalService);
}
@Test
void doSomething() {
Mockito.when(externalService.getData())
.thenReturn("Mock data");
String actual = someService.doSomething();
Assertions.assertEquals("Mock data", actual);
}
}
还有一些方法可以通过模拟构造函数来模拟整个 bean。为此,我们必须使用@Observes 注释
@HelidonTest
public abstract class HelidonTestHelper {
private MockedConstruction<ExternalService> mockedConstruction;
void init(@Priority(1) @Observes @Initialized(ApplicationScoped.class) ContainerInitialized containerInitialized) {
mockedConstruction = Mockito.mockConstruction(ExternalService.class);
//mock common beans here. This will be executed once application scope is loaded.
}
void onStop(@Priority(1) @Observes @Destroyed(ApplicationScoped.class) ContainerShutdown containerShutdown) {
//do cleanup here if needed.
mockedConstruction.closeOnDemand();
}
}
完成上述操作后,您可以扩展我们创建的助手 class,而不是 helidon 测试。
class SomeServiceTest extends HelidonTestHelper {
@Inject
private SomeService someService;
@Inject //this will be a mock
private ExternalService externalService;
@Test
void doSomething() {
Mockito.when(externalService.getData())
.thenReturn("Mock data");
String actual = someService.doSomething();
Assertions.assertEquals("Mock data", actual);
}
}
我有一个 Helidon 应用程序,我想测试它的(部分)。
我的测试用 @HelidonTest
注释,现在我想用一个 mock 替换一个 bean(并配置这个 mock,使用找到的所有其他 bean,但注入 mock)。
我确实想出了如何:
- 用测试实现替换一个 bean(单独 class):通过用
@Priority(1)
和@Alternative
注释测试实现 class 并通过注释测试提供它@AddBean(MyBeanTestImpl.class)
。- 但我无法创建一个模拟(使用 Mockito)作为个人 class。
- 产生一个
mock(MyBean.class)
:通过创建一个生产者方法并用@Produces
注释它:- 但它与真正的 bean 冲突并给出:“WELD-001409:类型的不明确依赖性...”
- 当我也用
@Alternative
注释它时,它会被忽略。 - 我不能用
@Priority(1)
注解,因为这个注解只能应用于类型和参数。
知道如何用模拟替换一个 bean 吗?
我尝试了 setter 注入来手动注入模拟 bean。
Class 测试中
@ApplicationScoped
public class SomeService {
private ExternalService externalService;
@Inject
public void setExternalService(ExternalService externalService) {
this.externalService = externalService;
}
public String doSomething() {
return externalService.getData();
}
}
测试Class
@HelidonTest
class SomeServiceTest {
@Inject
private SomeService someService;
private ExternalService externalService;
@BeforeEach
void setUp() {
externalService = Mockito.mock(ExternalService.class);
someService.setExternalService(externalService);
}
@Test
void doSomething() {
Mockito.when(externalService.getData())
.thenReturn("Mock data");
String actual = someService.doSomething();
Assertions.assertEquals("Mock data", actual);
}
}
还有一些方法可以通过模拟构造函数来模拟整个 bean。为此,我们必须使用@Observes 注释
@HelidonTest
public abstract class HelidonTestHelper {
private MockedConstruction<ExternalService> mockedConstruction;
void init(@Priority(1) @Observes @Initialized(ApplicationScoped.class) ContainerInitialized containerInitialized) {
mockedConstruction = Mockito.mockConstruction(ExternalService.class);
//mock common beans here. This will be executed once application scope is loaded.
}
void onStop(@Priority(1) @Observes @Destroyed(ApplicationScoped.class) ContainerShutdown containerShutdown) {
//do cleanup here if needed.
mockedConstruction.closeOnDemand();
}
}
完成上述操作后,您可以扩展我们创建的助手 class,而不是 helidon 测试。
class SomeServiceTest extends HelidonTestHelper {
@Inject
private SomeService someService;
@Inject //this will be a mock
private ExternalService externalService;
@Test
void doSomething() {
Mockito.when(externalService.getData())
.thenReturn("Mock data");
String actual = someService.doSomething();
Assertions.assertEquals("Mock data", actual);
}
}