我希望能够使用测试属性文件并仅覆盖一些属性。必须覆盖每一个属性都会变得很难看。
这是我用来测试模拟属性和在测试用例中使用现有属性的能力的代码
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApp.class)
@TestPropertySource(
locations = { "classpath:myapp-test.properties" },
properties = { "test.key = testValue" })
public class EnvironmentMockedPropertiesTest {
@Autowired private Environment env;
// @MockBean private Environment env;
@Test public void testExistingProperty() {
// some.property=someValue
final String keyActual = "some.property";
final String expected = "someValue";
final String actual = env.getProperty(keyActual);
assertEquals(expected, actual);
}
@Test public void testMockedProperty() {
final String keyMocked = "mocked.test.key";
final String expected = "mockedTestValue";
when(env.getProperty(keyMocked)).thenReturn(expected);
final String actual = env.getProperty(keyMocked);
assertEquals(expected, actual);
}
@Test public void testOverriddenProperty() {
final String expected = "testValue";
final String actual = env.getProperty("test.key");
assertEquals(expected, actual);
}
}
我发现的是:
@Autowired private Environment env;
testExistingProperty()
和testOverriddenProperty()
传递testMockedProperty()
失败@MockBean private Environment env;
testMockedProperty()
传递testExistingProperty()
和testOverriddenProperty()
失败有没有办法实现我的目标?
依赖关系:
<spring.boot.version>1.4.3.RELEASE</spring.boot.version>
...
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<!-- Starter for testing Spring Boot applications with libraries including JUnit,
Hamcrest and Mockito -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
</dependency>
答案 0 :(得分:1)
好的,我完成了这项工作,你需要使用Mockito来完成你想要的东西:
Maven依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.6.4</version>
</dependency>
测试类设置
import static org.mockito.Mockito.*;
import static org.springframework.test.util.AopTestUtils.getTargetObject;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApp.class)
@TestPropertySource(
locations = { "classpath:myapp-test.properties" },
properties = { "test.key = testValue" })
public class AnswerTest {
// This will be only for injecting, we will not be using this object in tests.
@Autowired
private Environment env;
// This is the reference that will be used in tests.
private Environment envSpied;
// Map of properties that you intend to mock
private Map<String, String> mockedProperties;
@PostConstruct
public void postConstruct(){
mockedProperties = new HashMap<String, String>();
mockedProperties.put("mocked.test.key_1", "mocked.test.value_1");
mockedProperties.put("mocked.test.key_2", "mocked.test.value_2");
mockedProperties.put("mocked.test.key_3", "mocked.test.value_3");
// We use the Spy feature of mockito which enabled partial mocking
envSpied = Mockito.spy((Environment) getTargetObject(env));
// We mock certain retrieval of certain properties
// based on the logic contained in the implementation of Answer class
doAnswer(new CustomAnswer()).when(envSpied).getProperty(Mockito.anyString());
}
测试用例
// Testing for both mocked and real properties in same test method
@Test public void shouldReturnAdequateProperty() {
String mockedValue = envSpied.getProperty("mocked.test.key_3");
String realValue = envSpied.getProperty("test.key");
assertEquals(mockedValue, "mocked.test.value_3");
assertEquals(realValue, "testValue");
}
实施Mockito的答案界面
// Here we define what should mockito do:
// a) return mocked property if the key is a mock
// b) invoke real method on Environment otherwise
private class CustomAnswer implements Answer<String>{
@Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] arguments = invocationOnMock.getArguments();
String parameterKey = (String) arguments[0];
String mockedValue = mockedProperties.get(parameterKey);
if(mockedValue != null){
return mockedValue;
}
return (String) invocationOnMock.callRealMethod();
}
}
}
尝试一下,如果一切都清楚,请告诉我。