2017-01-21 65 views
2

我想能夠使用測試屬性文件並僅覆蓋一些屬性。不得不重寫每一個屬性會變得很難。在春季環境中僅模擬選定的屬性

這是我使用測試我的嘲笑性質和測試用例使用現有的屬性能力

@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到accompish你在找什麼:

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()); 
    } 

測試用例的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(); 
     } 
    } 
} 

試試吧,讓我知道,如果一切都清楚這裏的

// 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"); 
    } 

實現。

+0

getTargetObject()來自哪裏? –

+1

對不起忘了進口。我已經更新了這個文章 –

+0

好吧,它實際上比較複雜,但是很有用,所以非常感謝。 :)我猜'@ MockBean'根本就沒有做我想做的事情,這是一種恥辱:我認爲嘲笑的想法是,你只會覆蓋你實際需要的東西(或者是間諜?)。 –