通过注解class创建带有限定符的@MockBean?
Create @MockBean with qualifier by annotating class?
在我的 Spring 引导测试中,我使用了 2 个具有不同限定符的模拟 bean:
@RunWith(SpringRunner.class)
@SpringBootTest
class HohoTest {
@MockBean @Qualifier("haha") IHaha ahaha;
@MockBean @Qualifier("hoho") IHaha ohoho;
}
由于我没有明确使用这些 bean,我宁愿将它们从 class 主体中移开,因为 @MockBean
注释现在是可重复的:
@RunWith(SpringRunner.class)
@SpringBootTest
@MockBean(IHaha.class)
@MockBean(IHaha.class)
class HohoTest {}
但是,我还需要传递一个限定符,因为它们具有相同的类型。知道如何实现吗?
在 class 级别声明 @MockBean
时,目前不支持提供 限定符。
如果你想得到这样的支持,我建议你request it in the Spring Boot issue tracker。
否则,您将需要继续在 @Qualifier
旁边的字段上声明 @MockBean
。
如果可以将模拟定义完全移出测试 class,您还可以在单独的 @Configuration
class:
中创建模拟
@Configuration
public class MockConfiguration
{
@Bean @Qualifier("haha")
public IHaha ahaha() {
return Mockito.mock(IHaha.class);
}
@Bean @Qualifier("hoho")
public IHaha ohoho() {
return Mockito.mock(IHaha.class);
}
}
我有一个类似的要求,即使用 @Order 注释注入 mocked 服务 bean。我还需要验证服务函数的调用次数。下面是我的实现。它可能会对某人有所帮助。
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceNameTest {
@Autowired private ServiceName serviceName;
// Important: Used to reset interaction count of our static
// bean objects before every test.
@Before
public void reset_mockito_interactions() {
Mockito.clearInvocations(MockServicesConfig.bean1);
Mockito.clearInvocations(MockServicesConfig.bean2);
}
@Configuration
public static class MockServicesConfig {
public static InterfaceName bean1;
public static InterfaceName bean2;
@Bean
@Order(1)
public InterfaceName bean1() {
bean1 = Mockito.mock(InterfaceName.class);
// Common when() stubbing
return bean1;
}
@Bean
@Order(2)
public InterfaceName vmpAdapter() {
bean2 = Mockito.mock(InterfaceName.class);
// Common when() stubbing
return bean2;
}
}
@Test
public void test_functionName_mock_invocation1() {
// Arrange --> Act --> Assert
// nullify other functions custom when() stub.
// updating this functions custom when() stub.
verify(MockServicesConfig.bean1, times(1)).functionName("");
}
@Test
public void test_functionName_mock_invocation2() {
// Arrange --> Act --> Assert
// nullify other functions custom when() stub.
// updating this functions custom when() stub.
verify(MockServicesConfig.bean1, times(1)).functionName("");
}
}
因为使用注释 @Qualifier
意味着按名称选择 bean,因此您可以使用如下代码为 mock 设置名称:
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {JsonMapperConfig.class})
public class IntegrationFlowTest {
@MockBean(name = "s3MessageRepository")
private S3Repository s3MessageRepository;
// etc
在我的 Spring 引导测试中,我使用了 2 个具有不同限定符的模拟 bean:
@RunWith(SpringRunner.class)
@SpringBootTest
class HohoTest {
@MockBean @Qualifier("haha") IHaha ahaha;
@MockBean @Qualifier("hoho") IHaha ohoho;
}
由于我没有明确使用这些 bean,我宁愿将它们从 class 主体中移开,因为 @MockBean
注释现在是可重复的:
@RunWith(SpringRunner.class)
@SpringBootTest
@MockBean(IHaha.class)
@MockBean(IHaha.class)
class HohoTest {}
但是,我还需要传递一个限定符,因为它们具有相同的类型。知道如何实现吗?
在 class 级别声明 @MockBean
时,目前不支持提供 限定符。
如果你想得到这样的支持,我建议你request it in the Spring Boot issue tracker。
否则,您将需要继续在 @Qualifier
旁边的字段上声明 @MockBean
。
如果可以将模拟定义完全移出测试 class,您还可以在单独的 @Configuration
class:
@Configuration
public class MockConfiguration
{
@Bean @Qualifier("haha")
public IHaha ahaha() {
return Mockito.mock(IHaha.class);
}
@Bean @Qualifier("hoho")
public IHaha ohoho() {
return Mockito.mock(IHaha.class);
}
}
我有一个类似的要求,即使用 @Order 注释注入 mocked 服务 bean。我还需要验证服务函数的调用次数。下面是我的实现。它可能会对某人有所帮助。
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceNameTest {
@Autowired private ServiceName serviceName;
// Important: Used to reset interaction count of our static
// bean objects before every test.
@Before
public void reset_mockito_interactions() {
Mockito.clearInvocations(MockServicesConfig.bean1);
Mockito.clearInvocations(MockServicesConfig.bean2);
}
@Configuration
public static class MockServicesConfig {
public static InterfaceName bean1;
public static InterfaceName bean2;
@Bean
@Order(1)
public InterfaceName bean1() {
bean1 = Mockito.mock(InterfaceName.class);
// Common when() stubbing
return bean1;
}
@Bean
@Order(2)
public InterfaceName vmpAdapter() {
bean2 = Mockito.mock(InterfaceName.class);
// Common when() stubbing
return bean2;
}
}
@Test
public void test_functionName_mock_invocation1() {
// Arrange --> Act --> Assert
// nullify other functions custom when() stub.
// updating this functions custom when() stub.
verify(MockServicesConfig.bean1, times(1)).functionName("");
}
@Test
public void test_functionName_mock_invocation2() {
// Arrange --> Act --> Assert
// nullify other functions custom when() stub.
// updating this functions custom when() stub.
verify(MockServicesConfig.bean1, times(1)).functionName("");
}
}
因为使用注释 @Qualifier
意味着按名称选择 bean,因此您可以使用如下代码为 mock 设置名称:
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {JsonMapperConfig.class})
public class IntegrationFlowTest {
@MockBean(name = "s3MessageRepository")
private S3Repository s3MessageRepository;
// etc