2016-12-03 122 views
-1

我知道我不應該測試這樣的無效方法,但我只是用一個簡單的例子來測試Mockito.doNothing()。Mockito.doNothing()一直返回空指針異常

我的服務類:

@Service 
public class Service{ 
    @Autowired 
    private Consumer<String, String> kafkaConsumer; 

    public void clearSubscribtions(){ 
     kafkaConsumer.unsubscribe(); 
    } 
} 

我的測試類:

@MockBean 
private Consumer<String, String> kafkaConsumer; 

@Test 
public void testClearSubscriptions() { 
    Service service = new Service(); 

    Mockito.doNothing().when(kafkaConsumer).unsubscribe(); 
    service.clearSubscriptions(); 
} 

測試保持與空指針異常失敗。當我調試它時,它進入服務類的clearSubscription方法,並且在kafkaConsumer.unsubscribe()的行上,kafkaConsumer爲null。但我嘲笑消費者,爲什麼它拋出空指針異常,我應該跳過這種方法,對吧?

編輯: 所有類的聲明:

@Autowired 
    private Consumer<String, String> kafkaConsumer; 

    @Autowired 
    private Service2 service2; 

    private final Object lock = new Object(); 

    private static Logger logger = LoggerFactory.getLogger(Service.class); 

    private HashMap<String, String> subscribedTopics = new HashMap<>(); 

想通了什麼是錯的,我需要自動線

+0

因爲我認爲該領域嘲笑從不嘲笑加樣。你似乎混合了Spring和Mockito。你能展示全班的聲明嗎?我認爲問題在那裏。 – davidxxx

回答

1

你實例化一個新的服務Service service = new Service();服務,但是從我所看到你永遠不會將模擬bean注入新的服務。

這裏是什麼,我認爲,如果你只使用的Mockito,你可以做,不需要實例化一個Spring容器(使用單一類爲便於例如不要在實際代碼做到這一點)的例子:

package com.sbp; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mock; 
import org.mockito.Mockito; 
import org.mockito.runners.MockitoJUnitRunner; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 

@RunWith(MockitoJUnitRunner.class) // run with mockitos runner so annotations are processed 
public class MyServiceTest { 

    public interface Consumer<T, R> { 

     public void unsubscribe(); 
    } 

    @Service 
    public class KafkaConsumer implements Consumer<String, String> { 

     @Override 
     public void unsubscribe() { 
     } 

    } 

    @Service 
    public class MyService { 

     @Autowired 
     private Consumer<String, String> kafkaConsumer; 

     public void clearSubscriptions() { 
      kafkaConsumer.unsubscribe(); 
     } 
    } 

    @Mock // tell mockito that this is a mock class - it will instantiate for you 
    private Consumer<String, String> kafkaConsumer; 

    @InjectMocks // tell mockito to inject the above mock into the class under test 
    private MyService service = new MyService(); 

    @Test 
    public void testClearSubscriptions() { 
     service.clearSubscriptions(); 
     Mockito.verify(kafkaConsumer, Mockito.times(1)).unsubscribe(); 
    } 
} 

如果你需要一個通過Spring使用MockBean或沒有和依賴的例子,讓我知道,我可以發佈。

更新:使用彈簧JUnit運行和使用彈簧啓動的mockbean註釋

package com.sbp; 

import com.sbp.MyServiceTest.TestContext.MyService; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mockito; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import org.springframework.boot.test.mock.mockito.MockBean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.stereotype.Service; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class) // run with spring 
@SpringBootTest(classes = MyServiceTest.TestContext.class) // make it a spring boot test so @MockBean annotation is processed, provide a dummy test context class 
public class MyServiceTest { 

    public interface Consumer<T, R> { 

     public void unsubscribe(); 
    } 

    @Configuration 
    public static class TestContext { 
     @Service 
     public class KafkaConsumer implements Consumer<String, String> { 

      @Override 
      public void unsubscribe() { 
      } 

     } 

     @Service 
     public class MyService { 

      @Autowired 
      private Consumer<String, String> kafkaConsumer; 

      public void clearSubscriptions() { 
       kafkaConsumer.unsubscribe(); 
      } 
     } 
    } 

    @MockBean // this will create a mockito bean and put it in the application context in place of the Kafka consumer bean defined in the TestContext class 
    private Consumer<String, String> kafkaConsumer; 

    @Autowired // inject the bean from the application context that is wired with the mock bean 
    private MyService myService; 

    @Test 
    public void testClearSubscriptions() { 
     myService.clearSubscriptions(); 
     Mockito.verify(kafkaConsumer, Mockito.times(1)).unsubscribe(); 
    } 
} 
+0

另請注意,我只是創建了一個dummy Consumer類,因爲我的環境中沒有實際的類 –

+0

有沒有辦法使用SpringJUnit4ClassRunner.class運行此類。如果我使用SpringJUnit4ClassRunner運行它,如果我從MockBean更改爲Mock for Consumer,則會收到應用程序初始化錯誤,因爲消費者在服務類中是AUTOWIRED – StephCurry3093

+0

我添加了一個使用SpringJUnit4ClassRunner與SpringBoots @MockBean註釋組合的示例。你將不得不適應你的環境/配置 –