2016-07-21 34 views
2

我想用我爲測試專門創建的類的模擬實現來替換彈簧引導應用程序中服務的自動裝配類。使用@InjectMocks將@Autowired字段替換爲模擬實現

我選擇創建這個mocked實現,因爲這個類的行爲太複雜了,不能用mockito來模擬,因爲它需要多個其他的mock本身。

我無法弄清楚如何將這個模擬實現注入到服務中。

這裏的情況小例子:

@Service 
public class ServiceIWantToTestImpl implements ServiceIWantToTest{ 

    @Autowired 
    ComplicatedDependency complicatedDependency; 

    @Override 
    public void methodUsingDependency(){ 
     String string = complicatedDependency.doSomething(); 
     System.out.println(string); 
    } 

} 


public class MockComplicatedDependency implements ComplicatedDepencency{ 

    public MockComplicatedDependency(...){ 
     // Inject other mocked objects into this mock 
    } 

    public String doSomthing(){ 
     // This would be a mocked version of this function for testing 
     return "test"; 
    } 

} 

@RunWith(MockitoJUnitRunner.class) 
public class TestingTheService(){ 
    @InjectMock 
    private static ServiceIWantToTest serviceIWantToTest = new ServiceIWantToTestImpl(); 

    @Mock 
    ComplicatedDependency mockComplicatedDependency; 

    @BeforeClass 
    public static void init(){ 
     mockComplicatedDependency = new MockComplicatedDependency(...); 
    } 

    @Test 
    public void testAttempt(){ 
     serviceIWantToTest.methodUsingDependency(); // This method calls complicatedDependency.doSomething() which does not run the mocked version in MockComplicatedDependency which I wanted to inject, and would always return null instead of the "test" string I put in this example. 
    } 

} 

回答

4

你必須使用註解的Mockito設置依存關係的類測試?

如果這不是主要的制約爲什麼不只是做普通簡單的設置和引進一個構造函數或ServiceIWantToTestImpl類的ComplicatedDependency領域的setter和直接設置在測試設置的依賴性ComplicatedDependency你的任何IMPL例如:

@Service 
public class ServiceIWantToTestImpl implements ServiceIWantToTest { 

    @Autowired 
    ComplicatedDependency complicatedDependency; 

    public ServiceIWantToTestImpl() { 

    } 

    public ServiceIWantToTestImpl(ComplicatedDependency complicatedDependency) { 
     this.complicatedDependency = complicatedDependency; 
    } 

    @Override 
    public void methodUsingDependency(){ 
     String string = complicatedDependency.doSomething(); 
     System.out.println(string); 
    } 
} 

public class TestingTheService { 

    private static ServiceIWantToTestImpl serviceIWantToTest; 

    @BeforeClass 
    public static void init(){ 
     serviceIWantToTest = new ServiceIWantToTestImpl(new MockComplicatedDependency()); 
    } 

    @Test 
    public void testAttempt() { 
     serviceIWantToTest.methodUsingDependency(); 
    } 

} 

這是一種方法。

,使其與工作的Mockito,你可能像這樣使用的,而不是@Mock @Spy:

@RunWith(MockitoJUnitRunner.class) 
public class TestingTheService { 

    @InjectMocks 
    private static ServiceIWantToTestImpl serviceIWantToTest = new ServiceIWantToTestImpl(); 

    @Spy 
    private static ComplicatedDependency complicatedDependency = new MockComplicatedDependency(); 

    @BeforeClass 
    public static void init() { 

    } 

    @Test 
    public void testAttempt() { 
     serviceIWantToTest.methodUsingDependency(); 
    } 

} 

雖然這是一個黑客攻擊的一位。我強烈建議您閱讀@Spy註釋的JavaDoc,並確保它的預期用途是您真正需要測試的內容。

+0

我嘗試使用@Spy,正如你所建議的那樣,它很棒。謝謝!我真的不想爲測試引入構造函數,我想讓Spring在應用程序中處理依賴注入。 –

+2

其實,構造函數級別的注入是推薦的方法,通常不鼓勵現場級別的注入 –

+1

正如@Milos提到的,Spring已經推薦了十多年的構造函數注入:http://spring.io/blog/2007/07/11/setter-injection-versus-constructor-injection-and-the-use-of-required /。沒有人應該再使用現場注入。 – jhyot