模拟基本抽象类的自动装配对象

时间:2019-03-22 16:01:39

标签: spring junit mockito abstract-class autowired

我正在为一个由抽象类扩展的类编写Junit测试用例。这个基础抽象类有一个与我正在测试的类中使用的不同类的自动装配对象。 我正在尝试在子类中进行模拟,但是模拟对象抛出NullPointerException。

示例:

// class I am testing
public class GetTransactionsForProcessorGroupActivity extends GetTransactionsBaseActivity {

    private static final Logger log = LogManager.getLogger(GetTransactionsForProcessorGroupActivity.class);

    public GetTransactionsForProcessorGroupActivity(ARHFactory arhFactory, MetricsFactory metricsFactory) {
        super(arhFactory, metricsFactory);
    }


    @Override
    protected List<OverseasTransaction> getOverseasTransactions(Document herdDocument)
            throws IllegalDateFormatException, ProcessorConfigurationException, DocumentException {
        final String paymentProcessorGroup = HerdDocumentUtils.getPaymentProcessor(herdDocument);
        final Date runDate = HerdDocumentUtils.getRunDate(herdDocument);

        final List<String> paymentProcessorList = ProcessorGroupLookup.getProcessorsFromGroup(paymentProcessorGroup);
        List<OverseasTransaction> overseasTransactionList = new ArrayList<OverseasTransaction>();
        List<ProcessorTransactionWindow> processingWindows = new ArrayList<ProcessorTransactionWindow>();

        for (final String processor : paymentProcessorList) {
            ProcessorTransactionWindow transactionWindow = ProcessorCalendarUtils.getProcessorTransactionWindow(processor, runDate);
            processingWindows.add(transactionWindow);

            final Date processingFromDate = transactionWindow.getFromDate();
            final Date processingToDate = transactionWindow.getToDate();
//NullpointerException on this line, as OverseasTransactionStore mock object returns null.
            final List<OverseasTransaction> transactions = overseasTransactionsStore
                    .queryOverseasTransactionsOnPPTimelineandDates(processor, processingFromDate, processingToDate);
            overseasTransactionList.addAll(transactions);
        }

        HerdDocumentUtils.putProcessingWindowDetails(herdDocument, processingWindows);
        return overseasTransactionList;
    }

}

// Base class
public abstract class GetTransactionsBaseActivity extends CoralHerdActivity implements ActionRequestHandler {

    private static final Logger log = LogManager.getLogger(GetTransactionsBaseActivity.class);

    @SuppressWarnings("unchecked")
    private static final Map<String, String> S3_CONFIGURATION = AppConfig.findMap(Constants.S3_CONFIGURATION_KEY);
    private static final String S3_BUCKET = S3_CONFIGURATION.get(Constants.BUCKET_NAME);

    private static final class Status {
        private static final String PROCESSOR_DETAILS_NOT_FOUND = "NoPaymentProcessorDetailsPresent";
        private static final String TRANSACTIONS_OBTAINED = "TransactionsObtained";
        private static final String NO_TRANSACTIONS_TO_BE_CONSIDERED = "NoTransactionsToBeConsidered";
        private static final String NEGATIVE_OR_ZERO_AMOUNT = "NegativeOrZeroAmount";
    }

    protected final ARHFactory arhFactory;

    protected final MetricsFactory metricsFactory;

    @Autowired
    OverseasTransactionsStore overseasTransactionsStore;

    @Autowired
    S3ClientProvider s3ClientProvider;


    protected abstract List<OverseasTransaction> getOverseasTransactions(Document herdDocument)
            throws IllegalDateFormatException, ProcessorConfigurationException, DocumentException;

    @Override
    public ActionResponse postActionRequest(final ActionRequest request) throws Exception {
        TimedARH timedARH = (TimedARH) arhFactory.createARH();
        timedARH.setHandler(this);
        return timedARH.handle(request);
    }

    public ActionResponse handle(final ActionRequest request) throws Exception {
        final Document herdDocument = HerdDocumentUtils.getFundFlowDocument(request);
        final Metrics metrics = MetricsLogger.getMetrics(metricsFactory);

        final String paymentProcessor = HerdDocumentUtils.getPaymentProcessor(herdDocument);

        try {
            final List<OverseasTransaction> overseasTransactionList;
            MetricsLogger.logFundFlowExecution(metrics, paymentProcessor);

            try {
                overseasTransactionList = getOverseasTransactions(herdDocument);
            } catch (ProcessorConfigurationException e) {
                return new ActionComplete(Status.PROCESSOR_DETAILS_NOT_FOUND, herdDocument);
            }

            if (CollectionUtils.isEmpty(overseasTransactionList)) {
                MetricsLogger.logTransactionMetrics(metrics, paymentProcessor, 0, BigDecimal.ZERO);
                return new ActionComplete(Status.NO_TRANSACTIONS_TO_BE_CONSIDERED, herdDocument);
            }

            final String s3ObjectKey = getS3ObjectKey(request, paymentProcessor);
            storeTransactionsInS3(overseasTransactionList, S3_BUCKET, s3ObjectKey);

            final int itemCount = overseasTransactionList.size();
            BigDecimal totalAmount = BigDecimal.ZERO;
            for (OverseasTransaction overseasTransaction : overseasTransactionList) {
                if (StringUtils.equalsIgnoreCase(overseasTransaction.getType(), Constants.TRANSACTION_TYPE_CHARGE)) {
                    totalAmount = totalAmount.add(overseasTransaction.getOverseasAmount());
                } else if (StringUtils.equalsIgnoreCase(overseasTransaction.getType(), Constants.TRANSACTION_TYPE_REFUND)) {
                    totalAmount = totalAmount.subtract(overseasTransaction.getOverseasAmount());
                }
            }

            MetricsLogger.logTransactionMetrics(metrics, paymentProcessor, itemCount, totalAmount);

            HerdDocumentUtils.putS3Location(herdDocument, S3_BUCKET, s3ObjectKey);
            HerdDocumentUtils.putTotalAmount(herdDocument, totalAmount);
            HerdDocumentUtils.putTransactionItemCount(herdDocument, itemCount);
            HerdDocumentUtils.putPaymentProcessor(herdDocument, paymentProcessor);

            if (totalAmount.compareTo(BigDecimal.ZERO) <= 0) {
                log.info("Total amount to disburse is zero or negative. {}", totalAmount);
                return new ActionComplete(Status.NEGATIVE_OR_ZERO_AMOUNT, herdDocument);
            }

            return new ActionComplete(Status.TRANSACTIONS_OBTAINED, herdDocument);
        } finally {
            MetricsLogger.closeMetrics(metrics);
        }
    }

}


// Test class
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({ "javax.management.*" })
@PrepareForTest({ HerdDocumentUtils.class, ProcessorGroupLookup.class })
public class GetTransactionsForProcessorGroupActivityTest extends AppConfigInitializedTestBase {

    private static HerdInput herdInput;
    private static HerdOutput herdOutput;
    private static final String paymentProcessorGroup = "BillDesk";
    private static final String paymentProcessorGroupNotFound = "IndiaPaymentGateway";

    @Mock
    ActionRequest request;

    @Mock
    WorkItemIdentifier workItemId;

    @Mock
    private CoralHerdActivity coralHerdActivity;

    @Mock
    Metrics metrics;

    @Mock
    Map<String, String> S3_CONFIGURATION_MAP;

    @Mock
    MetricsFactory metricsFactory;

    @Mock
    ARHFactory arhFactory;

    @Mock
    Document herdDocument;

    @Mock
    OverseasTransactionsStore overseasTransactionsStore;

    @Mock
    S3ClientProvider s3ClientProvider;

//    @InjectMocks
//    GetTransactionsForProcessorGroupActivity getTransactionsBaseActivityTest;

    // new GetTransactionsForProcessorGroupActivity(arhFactory, metricsFactory);

    @Before
    public void setup() {

        MockitoAnnotations.initMocks(this);
        PowerMockito.mockStatic(HerdDocumentUtils.class);
        // PowerMockito.mockStatic(ProcessorGroupLookup.class);
      //  GetTransactionsBaseActivity getTransactionsBaseActivity = new GetTransactionsBaseActivity(overseasTransactionsStore);

    }

    @Test
    public void testEnact() {
        GetTransactionsForProcessorGroupActivity getTransactionsForProcessorGroupActivity = Mockito
                .mock(GetTransactionsForProcessorGroupActivity.class, Mockito.CALLS_REAL_METHODS);
        Mockito.when(coralHerdActivity.enact(herdInput)).thenReturn(herdOutput);
        final HerdOutput actualHerdOutput = getTransactionsForProcessorGroupActivity.enact(herdInput);
        Assert.assertNotNull(actualHerdOutput);
    }

    @Test
    public void testgetpaymentProcessorList() throws Exception {
        Date date = new Date();
        List<String> paymentProcessorList;
        PowerMockito.when(HerdDocumentUtils.getPaymentProcessor(herdDocument)).thenReturn(paymentProcessorGroup);
        PowerMockito.when(HerdDocumentUtils.getRunDate(herdDocument)).thenReturn(date);
        paymentProcessorList = ProcessorGroupLookup.getProcessorsFromGroup(paymentProcessorGroup);
        assertNotNull(paymentProcessorList);
    }

    @Test(expected = ProcessorConfigurationException.class)
    public void testpaymentProcessorListNotFound() {
        Date date = new Date();
        PowerMockito.when(HerdDocumentUtils.getPaymentProcessor(herdDocument))
                .thenReturn(paymentProcessorGroupNotFound);
        PowerMockito.when(HerdDocumentUtils.getRunDate(herdDocument)).thenReturn(date);
        List<String> paymentProcessorList = ProcessorGroupLookup.getProcessorsFromGroup(paymentProcessorGroupNotFound);
        assertNotNull(paymentProcessorList);
    }

    @Test
    public void canGetOverseasTransactiontest() throws Exception {

        GetTransactionsForProcessorGroupActivity getTransactionsForProcessorGroupActivity = Mockito
                .mock(GetTransactionsForProcessorGroupActivity.class);
        // OverseasTransactionsStore overseasTransactionsStore =
        // Mockito.mock(OverseasTransactionsStoreImpl.class);

        Date date = new Date();
        MockitoAnnotations.initMocks(this);
        PowerMockito.when(HerdDocumentUtils.getPaymentProcessor(herdDocument)).thenReturn(paymentProcessorGroup);
        PowerMockito.when(HerdDocumentUtils.getRunDate(herdDocument)).thenReturn(date);
//        List<String> paymentProcessorList = new ArrayList<>();
//        paymentProcessorList.add("BillDesk");
//        PowerMockito.when(ProcessorGroupLookup.getProcessorsFromGroup(paymentProcessorGroup))
//                .thenReturn(paymentProcessorList);
        String fromDate = "Sat Mar 16 23:59:59 IST 2019";
        String toDate = "Sat Mar 16 23:59:59 IST 2019";
        DateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);

        List<OverseasTransaction> overseasTransactionList1 = createMockOverseasTransaction();

        Mockito.doReturn(overseasTransactionList1).when(overseasTransactionsStore)
                .queryOverseasTransactionsOnPPTimelineandDates(Mockito.isA(String.class), Mockito.isA(Date.class),
                        Mockito.isA(Date.class));
        Mockito.when(getTransactionsForProcessorGroupActivity.getOverseasTransactions(herdDocument))
                .thenCallRealMethod();
        List<OverseasTransaction> overseasTransactionList = getTransactionsForProcessorGroupActivity
                .getOverseasTransactions(herdDocument);
        assertNotNull(overseasTransactionList);
        // assertEquals(overseasTransactionList.getPaymentProcessorID(), actual);
    }

    private List<OverseasTransaction> createMockOverseasTransaction() {

        Date date = new Date();
        BigDecimal num = new BigDecimal(100001);
        List<OverseasTransaction> overseasTransactionList = new ArrayList<OverseasTransaction>();
        OverseasTransaction overseasTransaction = new OverseasTransaction();
        overseasTransaction.setPurchaseID("purchaseID");
        overseasTransaction.setSignatureID("signatureID");
        overseasTransaction.setPaymentProcessorTransactionID("paymentProcessorTransactionID");
        overseasTransaction.setType("Charge");
        overseasTransaction.setSubType("subType");
        overseasTransaction.setTransactionTimestamp(date);
        overseasTransaction.setPaymentMethod("paymentMethod");
        overseasTransaction.setTotalAmount(num);
        overseasTransaction.setOverseasAmount(num);
        overseasTransaction.setCurrency("currency");
        overseasTransaction.setMarketplaceID("marketplaceID");
        overseasTransaction.setOrderMetadata("orderMetadata");
        overseasTransaction.setDisbursementID("disbursementID");
        overseasTransaction.setReconState(1);
        overseasTransaction.setPaymentProcessorID("BillDesk");
        overseasTransaction.setRemittanceFileStatus("remittanceFileStatus");
        overseasTransaction.setCrowID("crowID");
        overseasTransaction.setSource("source");
        overseasTransactionList.add(overseasTransaction);
        return overseasTransactionList;
    }

}

在我的测试文件中,当我模拟OverseasTransaction对象时,它给了我NullPointerException。您对我们如何模拟这个有任何建议吗?在测试中,以上所有注释行都表明我已尝试过,但它们似乎仍然抛出相同的错误。

StackTrace错误:执行 canGetOverseasTransactiontest

不适用

java.lang.NullPointerException
at com.ingsfundflowservice.activity.GetTransactionsForProcessorGroupActivity.getOverseasTransactions(GetTransactionsForProcessorGroupActivity.java:71)
at com.ingsfundflowservice.activity.GetTransactionsForProcessorGroupActivityTest.canGetOverseasTransactiontest(GetTransactionsForProcessorGroupActivityTest.java:172)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)

2 个答案:

答案 0 :(得分:0)

您需要创建要为其编写测试的Class对象。即GetTransactionsForProcessorGroupActivity。您可以做什么

@RunWith(MockitoJUnitRunner.class)
public class GetTransactionsForProcessorGroupActivityTest {

  @InjectMocks
  private GetTransactionsForProcessorGroupActivity getTransactionsForProcessorGroupActivity;

  @Mock
  private OverseasTransaction overseastransaction;

  @Test
  public void test() {
    Mockito.when(overseastransaction.somemethod()).thenReturn(something);
  }
}

这将确保创建了getTransactionsForProcessorGroupActivity,并向模拟对象注入了OverseasTransaction。

请注意类注释 @RunWith 。这确保所有属性正确地注入了模拟对象。另外,您可以使用Mockito代替PowerMockito。

答案 1 :(得分:0)

您可以在抽象类中添加一个受保护的setter,然后在您的GetTransactionsForProcessorGroupActivity中可以在构造函数中调用setter。

然后,您只使用@Mock您需要设置的字段,然后使用@InjectMocks或更多建议的方法在@Setup方法中调用构造函数,包括要设置的模拟字段。