【问题标题】:How to mock a static method in side a public class using Power mockito?如何使用 Powermockito 在公共类中模拟静态方法?
【发布时间】:2017-09-21 08:15:01
【问题描述】:

大家好,我想模拟一个静态方法名称 ma​​pCreditInfo(UCIPin, creditAssessmentResults),它有两个参数 UCIPincreditAssessmentResults。 UCIPin 是 String 类型, creditAssessmentResults 是 List 此方法位于公共类 ResponseMapper 中 输入如下图:

private CreditInfo getAccountByUCI(String audiUser, String UCIPin) throws EnterpriseCustomerVerificationException {
    List<CreditAssessmentResult> creditAssessmentResults = creditInfoRepository.getUCISummary(UCIPin, audiUser);
    return ResponseMapper.mapCreditInfo(UCIPin, creditAssessmentResults);
}

注意:getAccountbyUCI 方法在另一个公共方法中被调用 类中的名称 executeCustomerVerification 企业客户验证服务

ResponseMapper 类

public class ResponseMapper {

public static CreditInfo mapCreditInfo(String UCIPin, List<CreditAssessmentResult> creditAssessmentResults) {
    CreditInfo creditInfo = new CreditInfo();

    creditInfo.setUCIPin(UCIPin);

    List<AccountCreditInfo> accountCreditInfos = new ArrayList<AccountCreditInfo>();
    for (CreditAssessmentResult creditAssessmentResult : creditAssessmentResults) {
        AccountCreditInfo accountCreditInfo = new AccountCreditInfo();
        accountCreditInfo.setDelinquenctBalance(creditAssessmentResult.getPastDueAmount());
        accountCreditInfo.setNonPayDisconnect(creditAssessmentResult.getNonpayDiscount());
        accountCreditInfo.setPreviousAccountNumber(creditAssessmentResult.getAccountNumber());
        accountCreditInfo.setUnreturnedEquipmentFlag(creditAssessmentResult.getUnreturnedEquipment());

        accountCreditInfos.add(accountCreditInfo);
    }
    creditInfo.setAccountCreditInfo(accountCreditInfos);

    return creditInfo;
}

}

我已经尝试过我的测试类的某些部分,如下所示: 测试类

@PrepareForTest( EnterpriseCustomerVerificationService.class)
@RunWith(PowerMockRunner.class)
public class EnterpriseCustomerVerificationServiceTest {

@InjectMocks
    private EnterpriseCustomerVerificationService enterpriseCustormerVerificationServiceMock ;
@Test
public void executeCustomerVerificationTest() throws Exception {
    List<ErrorResponse> errorResponses = getErrorResponse();
    List<String> mso = new ArrayList<String>();
    mso.add("a");
    mso.add("b");
    mso.add("c");
    AddressResponse addressResponse = getAddressResponse();
    String experianAuthorization = "experianAuthorization";
    String UCIPin = "110019";
    String auditUser = "ABC";

    CreditInfo credit  =   getCreditInfo();
    CreditCheck creditCheck = getcreditCheck();
    EnterpriseCustomerVerificationService spy = PowerMockito.spy(new EnterpriseCustomerVerificationService());

    PowerMockito.when(spy,PowerMockito.method(EnterpriseCustomerVerificationService.class,"executeCreditCheck",CreditCheck.class)).withArguments(Mockito.any()).thenReturn("@1");
    Mockito.when(creditInfoRepository.getUCISummary("110019", "test")).thenReturn(getCreditAssessmentResultList());

    PowerMockito.mockStatic(ResponseMapper.class);
    Mockito.when(ResponseMapper.mapCreditInfo(UCIPin, getCreditAssessmentResultList())).thenReturn(credit);

    CustomerVerification cv = spy
            .executeCustomerVerification(getCustomerVerificationRequest1(),
                    "101");
}

我的问题是如何使用 power Mockito 模拟 static mapCreditInfo 方法?

谢谢

【问题讨论】:

  • 你能告诉我们你到目前为止尝试了什么吗?您已经编写了一些尝试模拟此静态方法的测试方法,所以也许您可以更新问题以包含该尝试?
  • 好的等待@glitch
  • @glitch 请检查
  • 我已经更新了答案
  • @glitch 是的,当我临时创建新的测试用例时它工作正常谢谢:) 但是在我的 EnterpriseCustomerVerificationServiceTest 中工作时会出现空指针异常。

标签: java unit-testing junit mocking powermock


【解决方案1】:

像这样...

@RunWith(PowerMockRunner.class)
@PrepareForTest({ResponseMapper.class})
public class ATest {

    @Test
    public void testMockingStatic() {
        PowerMockito.mockStatic(ResponseMapper.class);

        // if you want to use specific argument matchers
        Mockito.when(ResponseMapper.mapCreditInfo(
            uciPin, creditAssessmentResults)
        ).thenReturn(creditInfo);

        // or if you want to match on any arguments passed into your static method ...
        Mockito.when(ResponseMapper.mapCreditInfo(
            ArgumentMatchers.anyString(), 
            ArgumentMatchers.anyList())
        ).thenReturn(creditInfo);

        // ...
    }
}

注意事项:

  • @PrepareForTest 使用您要模拟的静态方法准备类
  • PowerMockito.mockStatic 模拟该类的所有静态方法
  • 您可以使用标准 Mockito when/then 构造来告诉模拟的静态方法要返回什么
  • 上面的例子使用了这些依赖:
    • org.mockito:mockito-core:2.7.19
    • org.powermock:powermock-module-junit4:1.7.0
    • org.powermock:powermock-api-mockito2:1.7.0

更新 1: 基于您更新的问题,显示您的测试方法...

我的示例包括:@PrepareForTest({ResponseMapper.class}) 您的测试方法不是准备ResponseMapper,而是准备EnterpriseCustomerVerificationService。这就像您正在准备调用具有静态方法的类的类,而不是准备包含静态方法的类。

我强烈建议创建一个新的测试用例——只是暂时的——它看起来像我提供的那个,并用它来向自己展示如何模拟静态方法,一旦你对它感到满意,然后将它放入你的 @987654330 @。

【讨论】:

  • 我已经尝试过了,但它给出了以下错误:org.mockito.exceptions.misusing.MissingMethodInvocationException: when() 需要一个必须是“模拟方法调用”的参数。例如:when(mock.getArticles()).thenReturn(articles);
  • 该消息告诉您,您传递给Mockito.when() 的参数不是模拟。我建议从我提供的骨架开始,它可以工作。
  • 此外,此错误可能会出现,因为: 1. 您存根以下任一方法:final/private/equals()/hashCode() 方法。这些方法不能被存根/验证。不支持在非公共父类上声明的模拟方法。 2. 在 when() 中,您不会在 mock 上调用方法,而是在其他对象上调用方法。这是什么意思 ? @小故障
  • 但是这里讨论的方法 (ResponseMapper.mapCreditInfo()) 不是最终的或私有的,也不是等于或 hashCode。很难说您的尝试出了什么问题,因为我们看不到您的测试代码,但我的答案中的示例有效,所以我建议您从它开始并使用它(并将您自己的测试实现添加到其中)或者您仔细将其与您已经编写的内容进行比较并找出差异。
  • 如果你发现请投票给我的问题,这对某人有用:) :P
【解决方案2】:

是否可以更改源代码?如果是这样,也许您可​​以尝试在不使用任何模拟框架的情况下解决问题。

查看我对How To Java Unit Test a Complex Class的评论

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    相关资源
    最近更新 更多