【问题标题】:I am attempting to use Junit, mockito and PowerMock to create a unit test我正在尝试使用 Junit、mockito 和 PowerMock 创建单元测试
【发布时间】:2016-09-19 09:27:02
【问题描述】:

我正在尝试使用 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 类中放置一个调试器来模拟正确的类,以确保它在通过接口调用的方法上停止。

谁能告诉我为什么会发生这种情况以及如何解决它。

【问题讨论】:

  • 您也应该包含您的导入语句,以便您的示例完整。我不熟悉 PowerMock,据我所知,PowerMock 和 Mockito 都可以包含 Mock 注释。

标签: java unit-testing junit mockito powermock


【解决方案1】:

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

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

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

您还必须@RunWith(MockitoJUnitRunner.class),但由于您使用的是PowerMockRunner,因此这可能没有必要。

我建议您尽可能避免使用 PowerMock,或者至少在继续使用 PowerMock 编写测试之前让您的 mock 使用 Mockito。我从PowerMock wiki引用以下内容:

请注意,PowerMock 主要面向具有单元测试专业知识的人。将其交给初级开发人员可能弊大于利。

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

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

【讨论】:

  • 被模拟的方法之一是静态方法是模拟静态方法所需的 powermock 吗?
  • PowerMock 是模拟静态方法所必需的。我建议你应该避免模拟静态方法。相反,将静态方法调用包装在您创建的对象的实例方法中。现在可以在没有 PowerMock 的情况下模拟此实例方法。更好的是,不要在您正在测试的类中调用方法 - 将方法的结果传递给类构造函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2021-05-28
  • 1970-01-01
  • 2020-09-11
相关资源
最近更新 更多