2017-02-21 71 views
1

我熟悉SpringBoot並編寫了一個小應用程序。它有一個ProductRepository延伸CrudRepository。我ProductService是這樣的:在SpringBoot應用程序中使用Mockito

public interface ProductService { 
    Iterable<Product> listAllProducts(); 
    Product getProductById(Integer id); 
    Product saveProduct(Product product); 
    void deleteProduct(Integer id); 
} 

ProductServiceImpl級汽車電線ProductRepository和使用ProductRepository提供實現。

我的應用程序按預期運行,這就是我測試資源庫的方式。

@RunWith(SpringRunner.class) 
@SpringBootTest(classes = {RepositoryConfiguration.class}) 
public class ProductRepositoryTest { 
    private ProductRepository productRepository; 
    @Autowired 
    public void setProductRepository(ProductRepository productRepository) { 
    this.productRepository = productRepository; 
    } 
    @Test 
    public void testSaveProduct(){ 
    //setup product 
    Product product = new Product(); 
    product.setDescription("Shirt"); 
    product.setPrice(new BigDecimal("18.95")); 
    product.setProductId("1234");   
    assertNull(product.getId()); //null before save 
    productRepository.save(product); 
    assertNotNull(product.getId()); //not null after save 
    //fetch from DB 
    Product fetchedProduct = productRepository.findOne(product.getId()); 
    //should not be null 
    assertNotNull(fetchedProduct);  
} 
} 

我想知道我怎麼能單元測試ProductRepository沒有外部的依賴(這上面的測試有,因此不符合作爲一個單元測試,我相信這是更大的集成測試)。

另外,我怎麼能單元測試我ProductService?我試圖嘲弄ProductRepositoryProduct用的Mockito,像這樣:

public class ProductServiceImplTest { 
    private ProductServiceImpl productServiceImpl; 
    private ProductRepository productRepository; 
    private Product product; 

    @Before 
    public void setupMock() { 
    MockitoAnnotations.initMocks(this); 
    productServiceImpl=new ProductServiceImpl(); 
    productRepository = mock(ProductRepository.class); 
    product = mock(Product.class); 
    } 

    @Test 
    public void testRetrieveById() throws Exception { 
    when(productRepository.findOne(5)).thenReturn(product); 
    assertEquals(product, productServiceImpl.getProductById(5)); 
    } 
} 

但是,這是我所得到的:

java.lang.NullPointerException 
at  
    ProductServiceImpl.getProductById(ProductServiceImpl.java:24) 
at ProductServiceImplTest.testRetrieveById(ProductServiceImplTest.java:36) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke 
(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke 
(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall 
    (FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run 
(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:497) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) 

我使用了Mockito.mock()是否正確?此外,如果我使用Mockito.spy()代替,會有什麼區別?任何幫助將不勝感激。

回答

1

如果你想要編寫單元測試然後刪除用於一體化測試所有這些不必要的註釋。

還需要啓動嘲笑在@Before方法:

public class ProductServiceImplTest { 
    @InjectMocks 
    private ProductServiceImpl productServiceImpl; 
    @Mock 
    private ProductRepository productRepository; 
    @Mock 
    private Product product; 

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

我想在你的情況下,使用mock應該夠了。

,你應該使用的唯一一次spy是調用它正在測試而你的情況將是類:

productServiceImpl=new ProductServiceImpl(); 
prodServiceSpy = spy(productServiceImpl); 

和嘲笑的一些方法你不想要哪種實現被調用,或者調用測試場景所需的自定義實現。

+0

感謝您的明確答覆 - 正是我所期待的。我編輯了這個問題,但仍然無法弄清楚爲什麼會拋出NullPointerException。 – user2693135

+0

您需要將存儲庫或任何其他依賴項注入到服務中。我已經更新了使用mockito註釋的例子..使生活更輕鬆 –

+0

工程就像一個魅力 - 謝謝。標記爲已接受。 – user2693135

相關問題