swa*_*ter 9 spring-test junit4 spring-boot
情况和问题:在Spring Boot中,如何将一个或多个模拟类/ bean注入应用程序以进行集成测试?StackOverflow上有一些答案,但它们专注于Spring Boot 1.4之前的情况,或者只是不适合我.
背景是,在下面的代码中,Settings的实现依赖于第三方服务器和其他外部系统.Settings的功能已经在单元测试中进行了测试,因此对于完整的集成测试,我想模拟对这些服务器或系统的依赖性,并提供虚拟值.
MockBean将忽略所有现有bean定义并提供虚拟对象,但此对象不会在注入此类的其他类中提供方法行为.使用@Before方法在测试之前设置行为不会影响注入的对象,也不会在其他应用程序服务(如AuthenticationService)中注入.
我的问题:如何将我的bean注入应用程序上下文?我的测试:
package ch.swaechter.testapp;
import ch.swaechter.testapp.utils.settings.Settings;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.test.context.junit4.SpringRunner;
@TestConfiguration
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyApplication.class})
public class MyApplicationTests {
@MockBean
private Settings settings;
@Before
public void before() {
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
}
@Test
public void contextLoads() {
String applicationsecret = settings.getApplicationSecret();
System.out.println("Application secret: " + applicationsecret);
}
}
Run Code Online (Sandbox Code Playgroud)
并且下面应该使用模拟类的服务,但是没有收到这个模拟类:
package ch.swaechter.testapp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AuthenticationServiceImpl implements AuthenticationService {
private final Settings settings;
@Autowired
public AuthenticationServiceImpl(Settings settings) {
this.settings = settings;
}
@Override
public boolean loginUser(String token) {
// Use the application secret to check the token signature
// But here settings.getApplicationSecret() will return null (Instead of Application Secret as specified in the mock)!
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
Ser*_*erg 14
在指定其模拟行为之前,您似乎正在使用"设置"对象.你必须跑
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
Run Code Online (Sandbox Code Playgroud)
在配置设置期间.为了防止您可以创建特殊配置类以进行测试.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyApplication.class, MyApplicationTest.TestConfig.class})
public class MyApplicationTest {
private static final String SECRET = "Application Secret";
@TestConfiguration
public static class TestConfig {
@Bean
@Primary
public Settings settingsBean(){
Settings settings = Mockito.mock(Settings.class);
Mockito.when(settings.getApplicationSecret()).thenReturn(SECRET);
Mockito.doReturn(SECRET).when(settings).getApplicationSecret();
return settings;
}
}
.....
}
Run Code Online (Sandbox Code Playgroud)
另外我建议你使用下一个表示法进行模拟:
Mockito.doReturn(SECRET).when(settings).getApplicationSecret();
Run Code Online (Sandbox Code Playgroud)
它不会运行settings :: getApplicationSecret
当您使用@MockBean注释字段时,spring将创建注释类的模拟并使用它来自动装配应用程序上下文的所有bean。
您不能自己创建模拟
Settings settings = Mockito.mock(Settings.class);
Run Code Online (Sandbox Code Playgroud)
这将创建第二个模拟,从而导致所描述的问题。
解决方案 :
@MockBean
private Settings settings;
@Before
public void before() {
Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
}
@Test
public void contextLoads() {
String applicationsecret = settings.getApplicationSecret();
System.out.println("Application secret: " + applicationsecret);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7582 次 |
| 最近记录: |