我正在努力让我的测试单元启动并运行,我遇到了一个奇怪的问题。我的应用程序使用注释为@Component的ApplicationListener类来在启动期间执行操作。
在测试期间,我已经模拟了包含逻辑的服务,但我发现即使Mockito在指令在控制器范围内运行良好时,也没有为此ApplicationListener类初始化bean:而不是返回我定义的内容在测试单元中,它返回false或null - 取决于服务中每个方法返回的数据类型。
由于我没有找到任何方法从ApplicationListener类的测试单元初始化模拟服务,我决定将其排除。为此,我尝试了不同的方法,最常用的方法是创建测试应用程序上下文并更改其配置。不幸的是,我所看到的一切都没有用 - 所以我在这里寻求帮助。如果可能的话,我宁愿不接触ApplicationListener类并在测试代码中进行所有相关的编码。
我对两种可能的解决方案中的任何一种感兴趣,如果可以的话:
1.-在ApplicationListener执行期间获取模拟行为,但我已经读过某些地方无法完成此操作
2.-以某种方式从测试单元中排除@Component。
TestUnit.Java :
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class TestConfigurationService {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@MockBean
private MockService mockService;
private void initMockBean () throws Exception {
when(mockService.isDoingSomething()).thenReturn(true);
}
@Before
public void setup() throws Exception {
// Spring mock context application setup
this.mockMvc = webAppContextSetup(webApplicationContext).build();
// Initialize ConsulService mock bean
initMockBean ();
}
}
TestApplication.java
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages="my.base.package", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = StartupConfiguration.class))
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
除了代码中显示的内容外,我还在文件TestApplication.java中尝试了这个注释:
@SpringBootApplication(exclude={StartupConfiguration.class})
StartupConfiguration.java
@Component
public class StartupConfiguration implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private ConfigurationService configurationService;
@Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
try {
configurationService.updateConfiguration();
} catch (Exception e) {
throw new RuntimeException ("Error", e);
}
}
}
ConfigurationService.java
public interface ConfigurationService {
public void updateConfiguration () throws Exception;
}
ConfigurationServiceImpl.java
@Service
@Transactional
public class ConfigurationServiceImpl implements ConfigurationService {
@Autowired
private MService mockService;
@Override
public void updateConfiguration() throws Exception {
if (mockService.isDoingSomething()==false)
throw new Exception ("Something went wrong");
}
}
版本:
Spring Boot 1.5.4.RELEASE,
Java 1.8
答案 0 :(得分:0)
您可以创建相同类型的模拟bean,并使用@Primary
注释标记它以替换真实bean。您可以通过测试此类配置来实现此目的:
@Configuration
@Import(TestApplication.class)
public class TestConfiguration {
@Bean
@Primary
public ConfigurationService configurationService() {
return Mockito.mock(ConfigurationService.class);
}
}
然后在测试中得到这个模拟:
...
public class TestConfigurationService {
...
@Autowired
ConfigurationService configurationService;
@Before
public void setUp() {
when(mockService.isDoingSomething()).thenReturn(true);
}
}
答案 1 :(得分:0)
谢谢,araxn1d。你的回答给了我解决这个问题的线索。
我在TestUnit.java中模拟了StartupConfiguration类:
@MockBean
private StartupConfiguration startupConfiguration;
虽然在这种情况下我很幸运:应用程序听众没有返回方法,所以他们在测试配置时不需要。如果我要求某些方法返回例如true或值,则此方法将不适用。
但至少对于应用程序监听器来说,这已经足够了。