2013-09-25 48 views
8

我正面臨着在Spring框架內嘲笑其他服務內部注入服務的問題。這裏是我的代碼:mockito在另一個彈簧服務中模擬服務

@Service("productService") 
public class ProductServiceImpl implements ProductService { 

    @Autowired 
    private ClientService clientService; 

    public void doSomething(Long clientId) { 
     Client client = clientService.getById(clientId); 
     // do something 
    } 
} 

我想嘲笑我的測試裏面ClientService,所以我嘗試了以下內容:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:/spring-config.xml" }) 
public class ProductServiceTest { 

    @Autowired 
    private ProductService productService; 

    @Mock 
    private ClientService clientService; 

    @Test 
    public void testDoSomething() throws Exception { 
     when(clientService.getById(anyLong())) 
       .thenReturn(this.generateClient()); 

     /* when I call this method, I want the clientService 
     * inside productService to be the mock that one I mocked 
     * in this test, but instead, it is injecting the Spring 
     * proxy version of clientService, not my mock.. :(
     */ 
     productService.doSomething(new Long(1)); 
    } 

    @Before 
    public void beforeTests() throws Exception { 
     MockitoAnnotations.initMocks(this); 
    } 

    private Client generateClient() { 
     Client client = new Client(); 
     client.setName("Foo"); 
     return client; 
    } 
} 

productServiceclientService是Spring代理版本,而不是模仿我想。 Mockito可以做到我想要的嗎?

回答

0

有更多的方式來實現這一目標,最簡單的方法來做到這將是don't use field injection, but setter injection這意味着你應該有:

@Autowired 
public void setClientService(ClientService clientService){...} 

在你的服務類,那麼你可以注入你的模擬到服務測試類:

@Before 
public void setUp() throws Exception { 
    productService.setClientService(mock); 
} 

important:如果這僅僅是一個單元測試,請考慮不要使用SpringJUnit4ClassRunner.class,但MockitoJunitRunner.class,這樣你也可以使用領域注入你的領域。

+1

謝謝,我想,解決方案和工作得很好,但我不能在服務改爲setter注入,所以我的解決辦法是刪除我的測試中的自動裝配註釋並手動創建服務,如下所示:'@InjectMocks private ProductService productService = new ProductServiceImpl();' – br4zuca

+0

@ br4zuca您可以使用'@InjectMocks private ProductService productService'完成它,不要初始化它手動,讓模擬ito做到這一點。 – Jaiwo99

+1

我試着用'@InjectMocks'離開mockito init'productService',但沒有工作,因爲'ProductService'是一個接口,它拋出:'org.mockito.exceptions.base.MockitoException:類型'ProductService'是一個接口',所以它不能實例化。 – br4zuca

4

你需要註釋ProductService@InjectMocks

@Autowired 
@InjectMocks 
private ProductService productService; 

這將注入ClientService模擬到您的ProductService

+0

感謝Debojit,但我意識到無法將spring的注入與mockito的模擬注入結合使用...所以我的解決方案是通過手動創建ProductService並用'@InjectMocks'注入像你所說的模擬,但不使用'@ Autowired': '@InjectMocks private ProductService productService = new ProductServiceImpl();' – br4zuca

+0

這很奇怪。我一直在使用這兩個註釋。你測試過了嗎?在使用這兩者時是否有任何異常? –

+0

是的,我測試了很多,即使使用ProductService上的@InjectMocks,clientService裏面的客戶端也是使用spring代理加載,而不是模擬對象。也許你使用的spring-test版本與我使用的不同,我的版本是3.0.1.RELEASE,你的版本是什麼? – br4zuca

0

除了

@Autowired 
@InjectMocks 
private ProductService productService; 

添加以下方法

@Before 
public void setup() { 
    MockitoAnnotations.initMocks(this); 
}