我正在尝试使用Junit,mockito和PowerMock来创建单元测试

时间:2016-09-19 09:27:03

标签: java unit-testing junit mockito powermock

我正在尝试使用Junit,mockito和PowerMock来创建单元测试

我的问题是我试图模拟的一个类是返回一个空对象

这是我的代码

    @RunWith(PowerMockRunner.class)
@PrepareForTest(ClientBuilder.class)
public class SolrPopulateApplicationTest {

   @Mock
   ClientConfig clientConfig;

   @Mock
   Client client;

   @Mock
   Response response;

   @Mock
   JerseyClient jerseyClient;

   @Mock (answer = Answers.RETURNS_DEEP_STUBS)
   JerseyWebTarget jerseyWebTarget;

   @InjectMocks
   @Autowired
   SolrPopulateApplication solrPopulateApplication;

   @Test
   public void indexTest(){

       PowerMockito.mockStatic(ClientBuilder.class);

       ClientBuilder cli = Mockito.mock(ClientBuilder.class);

    when(ClientBuilder.newClient(Matchers.any())).thenReturn(client);

       when(jerseyClient.target(Matchers.anyString())).thenReturn(jerseyWebTarget);

       when(jerseyWebTarget.path(Matchers.anyString())
               .queryParam(Matchers.anyString(),Matchers.anyString())
       .request(Matchers.anyString())
               .header(Matchers.anyString(),Matchers.anyString())
       .post(Matchers.any())).thenReturn(response);

       boolean var = solrPopulateApplication.index("test","test");

   }
}

如果在设置完所有模拟之后放置调试断点,我将得到以下内容

    client = {Client$$EnhancerByMockitoWithCGLIB$$7f4c6946@1705} "client"
response = {Response$$EnhancerByMockitoWithCGLIB$$b85fdf42@1704} "response"
jerseyWebTarget = {JerseyWebTarget$$EnhancerByMockitoWithCGLIB$$7d7091b9@1703} "null"
solrPopulateApplication = {SolrPopulateApplication@1702} 
jerseyClient = {JerseyClient$$EnhancerByMockitoWithCGLIB$$6437ba91@1701} "jerseyClient"
cli = {ClientBuilder$$EnhancerByMockitoWithCGLIB$$20196b6d@1700} "Mock for ClientBuilder, hashCode: 2080643905"
this = {SolrPopulateApplicationTest@1695}

你可以看到jerseyWebClient是一个NULL,当我尝试运行测试时,这会导致nullpointerexception。

我尝试从@mock语句中删除(answer = Answers.RETURNS_DEEP_STUBS),这没什么区别。

正在测试的方法实际上调用了一个实现JerseyWebTarget类的接口。我已经确定我试图通过在JerseyWebTarget类中放置一个调试器来模拟正确的类,以确保它停止在通过接口调用的方法上。

任何人都可以告诉我为什么会这样,以及如何解决它。

1 个答案:

答案 0 :(得分:2)

假设您使用的是Mockito @Mock注释...

要使用Mockito @Mock注释,您必须在每次测试之前执行特定的代码行。您可以在设置方法中执行此操作:

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

您还必须@RunWith(MockitoJUnitRunner.class),但在使用PowerMockRunner时,可能没有必要这样做。

我建议你尽量避免使用PowerMock,或者至少让你的模拟器与Mockito合作,然后继续用PowerMock编写测试。我引用PowerMock wiki中的以下内容:

  

请注意,PowerMock主要面向具有单元测试专业知识的人员。把它放在初级开发人员手中可能会带来更多弊大于利。

除非在此有必要使用PowerMock的特定原因,否则请避免使用。例如,您可以将JerseyWebTarget传递到SolrPopulateApplication的构造函数中,而不是直接调用您正在测试的类中的ClientBuilder

此外,PowerMock和Mockito可能并不总能在一起玩得很好。例如,请参阅this bug