From 87a71a0ea2189abc038dfe990cddc0fb549fdb21 Mon Sep 17 00:00:00 2001 From: sshropshire <58225613+sshropshire@users.noreply.github.com> Date: Tue, 30 May 2023 16:12:37 -0500 Subject: [PATCH] Remove Powermock (#731) * Remove powermock legacy build.gradle variables. * Remove powermock dependency from GooglePlay unit tests. * Remove powermock dependency from AmericanExpress unit tests. * Remove powermock dependency from PayPalDataCollector unit tests. * Remove powermock test dependency from BraintreeCore unit tests. * Remove powermock dependency from BraintreeDataCollector. * Remove power mock dependency from sepa direct debit. * Remove powermock from Card module test dependencies. * Remove powermock from Local Payment module test dependencies. * Remove power mock from paypal module unit tests. * Remove powermock dependency from SamsungPay module unit tests. * Remove powermock dependency from Venmo module unit tests. * Remove powermock dependency from UnionPay module unit tests. * Remove powermock from TestUtils module compile only dependencies. * Update mockito version to latest and migrate shared utils away from power mock. * Migrate MockBraintreeClientBuilder to updated mockito matchers. * Fix AmericanExpress module mockito upgrade build errors. * Fix Card module mockito upgrade errors. * Fix GooglePayClient mockito upgrade errors. * Fix LocalPayment mockito upgrade errors. * Fix PayPal module mockito upgrade errors. * Fix UnionPay mockito upgrade issues. * Fix Venmo mockito upgrade errors. * Update broken mockito imports in PayPalNativeCheckout. * Modify ThreeDSecure module to use mockito core instead of powermock. * Refactor PayPalNativeCheckoutClientUnitTest to use mockk. * Remove power mock from paypal native checkout module. * Migrate VisaCheckoutAccountUnitTest to Kotlin and mockk. * Refactor VisaCheckoutClient to no longer use powermock. * Remove powermock dependency from visa checkout module. * Remove mention of powermock from build.gradle. * Remove Google Pay duct tape for mockito unit test. * Port CardinalClient updated unit tests. * Remove unused stub. --- ACKNOWLEDGEMENTS.md | 1 - AmericanExpress/build.gradle | 5 +- .../api/AmericanExpressClientUnitTest.java | 18 +- BraintreeCore/build.gradle | 1 + BraintreeDataCollector/build.gradle | 5 +- Card/build.gradle | 5 +- .../api/CardClientUnitTest.java | 18 +- GooglePay/build.gradle | 5 +- .../api/GooglePayClientUnitTest.java | 8 +- LocalPayment/build.gradle | 5 +- .../api/LocalPaymentClientUnitTest.java | 16 +- .../api/MockLocalPaymentApiBuilder.java | 2 +- PayPal/build.gradle | 5 +- .../api/MockPayPalInternalClientBuilder.java | 8 +- .../api/PayPalClientUnitTest.java | 6 +- .../api/PayPalInternalClientUnitTest.java | 10 +- PayPalDataCollector/build.gradle | 5 +- PayPalNativeCheckout/build.gradle | 5 +- .../PayPalNativeCheckoutInternalClient.java | 5 - ...lNativeCheckoutInternalClientCallback.java | 12 + .../api/MockPayPalInternalClientBuilder.java | 60 --- .../api/MockkPayPalInternalClientBuilder.kt | 46 ++ .../PayPalNativeCheckoutClientUnitTest.java | 397 ------------------ .../api/PayPalNativeCheckoutClientUnitTest.kt | 374 +++++++++++++++++ ...lNativeCheckoutInternalClientUnitTest.java | 27 +- .../org.mockito.plugins.MockMaker | 1 + .../extensions/configuration.properties | 2 - SEPADirectDebit/build.gradle | 5 +- .../api/SEPADirectDebitApiUnitTest.java | 2 +- SamsungPay/build.gradle | 5 +- SharedUtils/build.gradle | 6 +- .../api/HttpClientUnitTest.java | 12 +- .../api/SynchronousHttpClientUnitTest.java | 16 +- TestUtils/build.gradle | 5 +- .../api/MockApiClientBuilder.java | 8 +- .../api/MockBraintreeClientBuilder.java | 15 +- .../api/MockkApiClientBuilder.kt | 50 +++ ThreeDSecure/build.gradle | 16 +- .../api/CardinalClientUnitTest.java | 284 ------------- .../api/CardinalClientUnitTest.kt | 270 ++++++++++++ .../api/MockCardinalClientBuilder.java | 12 +- .../api/ThreeDSecureAPIUnitTest.java | 14 +- .../api/ThreeDSecureActivityUnitTest.java | 30 +- .../api/ThreeDSecureClientUnitTest.java | 12 +- ...ThreeDSecureLifecycleObserverUnitTest.java | 6 +- .../api/ThreeDSecureV2UnitTest.java | 8 +- UnionPay/build.gradle | 5 +- .../api/UnionPayClientUnitTest.java | 28 +- Venmo/build.gradle | 5 +- .../api/MockVenmoApiBuilder.java | 2 +- .../api/VenmoClientUnitTest.java | 12 +- .../api/VenmoLifecycleObserverUnitTest.java | 6 +- VisaCheckout/build.gradle | 6 +- .../api/VisaCheckoutAccountUnitTest.java | 86 ---- .../api/VisaCheckoutAccountUnitTest.kt | 73 ++++ .../api/VisaCheckoutClientUnitTest.java | 212 ---------- .../api/VisaCheckoutClientUnitTest.kt | 170 ++++++++ build.gradle | 15 +- 58 files changed, 1160 insertions(+), 1288 deletions(-) create mode 100644 PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientCallback.java delete mode 100644 PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java create mode 100644 PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockkPayPalInternalClientBuilder.kt delete mode 100644 PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.java create mode 100644 PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.kt create mode 100644 PayPalNativeCheckout/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker delete mode 100644 PayPalNativeCheckout/src/test/resources/org/powermock/extensions/configuration.properties create mode 100644 TestUtils/src/main/java/com/braintreepayments/api/MockkApiClientBuilder.kt delete mode 100644 ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.java create mode 100644 ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.kt delete mode 100644 VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.java create mode 100644 VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.kt delete mode 100644 VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.java create mode 100644 VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.kt diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index 85f45031d5..a10f0542e8 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -13,7 +13,6 @@ The Braintree SDK uses code from the following libraries: * [leakcanary](https://github.com/square/leakcanary), Apache License Version 2.0 * [mailable-log](https://github.com/lkorth/mailable-log), MIT License * [Mockito](https://github.com/mockito/mockito), MIT License - * [PowerMock](https://github.com/jayway/powermock), Apache License Version 2.0 * [Retrofit](https://github.com/square/retrofit), Apache License Version 2.0 * [Robolectric](https://github.com/robolectric/robolectric), MIT License * [SDK Manager Plugin](https://github.com/JakeWharton/sdk-manager-plugin), Apache License Version 2.0 diff --git a/AmericanExpress/build.gradle b/AmericanExpress/build.gradle index 0de64e36b5..2b04d7f0d9 100644 --- a/AmericanExpress/build.gradle +++ b/AmericanExpress/build.gradle @@ -37,10 +37,7 @@ dependencies { implementation deps.annotation testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation project(':TestUtils') } diff --git a/AmericanExpress/src/test/java/com/braintreepayments/api/AmericanExpressClientUnitTest.java b/AmericanExpress/src/test/java/com/braintreepayments/api/AmericanExpressClientUnitTest.java index f264f3ab69..40fbd2b765 100644 --- a/AmericanExpress/src/test/java/com/braintreepayments/api/AmericanExpressClientUnitTest.java +++ b/AmericanExpress/src/test/java/com/braintreepayments/api/AmericanExpressClientUnitTest.java @@ -1,19 +1,19 @@ package com.braintreepayments.api; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.robolectric.RobolectricTestRunner; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.robolectric.RobolectricTestRunner; + @RunWith(RobolectricTestRunner.class) public class AmericanExpressClientUnitTest { @@ -73,7 +73,7 @@ public void getRewardsBalance_callsListenerWithRewardsBalanceWithErrorCode_OnIne ArgumentCaptor amexRewardsCaptor = ArgumentCaptor.forClass(AmericanExpressRewardsBalance.class); - verify(amexRewardsCallback).onResult(amexRewardsCaptor.capture(), (Exception) isNull()); + verify(amexRewardsCallback).onResult(amexRewardsCaptor.capture(), isNull()); AmericanExpressRewardsBalance rewardsBalance = amexRewardsCaptor.getValue(); assertNotNull(rewardsBalance); diff --git a/BraintreeCore/build.gradle b/BraintreeCore/build.gradle index ea1376c758..4f38f5592d 100644 --- a/BraintreeCore/build.gradle +++ b/BraintreeCore/build.gradle @@ -77,6 +77,7 @@ dependencies { testImplementation deps.robolectric testImplementation deps.androidxTestCore testImplementation deps.junitTest + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation deps.mockk testImplementation project(':PayPal') diff --git a/BraintreeDataCollector/build.gradle b/BraintreeDataCollector/build.gradle index 73c080fdef..9f0d49eab9 100644 --- a/BraintreeDataCollector/build.gradle +++ b/BraintreeDataCollector/build.gradle @@ -48,10 +48,7 @@ dependencies { testImplementation deps.mockitoCore testImplementation deps.androidxTestCore testImplementation deps.jsonAssert - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation project(':TestUtils') diff --git a/Card/build.gradle b/Card/build.gradle index 8bdc5c6183..456cbdcd5a 100644 --- a/Card/build.gradle +++ b/Card/build.gradle @@ -37,10 +37,7 @@ dependencies { implementation deps.annotation testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation project(':TestUtils') testImplementation project(':ThreeDSecure') diff --git a/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java b/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java index ac609ef456..58680b83cb 100644 --- a/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java +++ b/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java @@ -1,5 +1,13 @@ package com.braintreepayments.api; +import static junit.framework.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.content.Context; import org.json.JSONException; @@ -12,14 +20,6 @@ import org.mockito.Mockito; import org.robolectric.RobolectricTestRunner; -import static junit.framework.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(RobolectricTestRunner.class) public class CardClientUnitTest { @@ -76,7 +76,7 @@ public void tokenize_whenGraphQLEnabled_tokenizesWithGraphQL() throws JSONExcept sut.tokenize(card, cardTokenizeCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(CardNonce.class); - verify(cardTokenizeCallback).onResult(captor.capture(), (Exception) isNull()); + verify(cardTokenizeCallback).onResult(captor.capture(), isNull()); CardNonce cardNonce = captor.getValue(); assertEquals("3744a73e-b1ab-0dbd-85f0-c12a0a4bd3d1", cardNonce.getString()); diff --git a/GooglePay/build.gradle b/GooglePay/build.gradle index cef459bb9a..910a7e8bd4 100644 --- a/GooglePay/build.gradle +++ b/GooglePay/build.gradle @@ -48,10 +48,7 @@ dependencies { testImplementation deps.androidxTestRules testImplementation deps.androidxTestRunner testImplementation deps.playServicesWallet - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.robolectric testImplementation deps.jsonAssert testImplementation deps.coreKtx diff --git a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java index 47f57c2082..9b82901b6c 100644 --- a/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java +++ b/GooglePay/src/test/java/com/braintreepayments/api/GooglePayClientUnitTest.java @@ -10,10 +10,10 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -1222,7 +1222,7 @@ public void tokenize_withCardToken_returnsGooglePayNonce() { sut.tokenize(pd, activityResultCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(PaymentMethodNonce.class); - verify(activityResultCallback).onResult(captor.capture(), (Exception) isNull()); + verify(activityResultCallback).onResult(captor.capture(), isNull()); assertTrue(captor.getValue() instanceof GooglePayCardNonce); } diff --git a/LocalPayment/build.gradle b/LocalPayment/build.gradle index 220ce0a0c0..dc53965f99 100644 --- a/LocalPayment/build.gradle +++ b/LocalPayment/build.gradle @@ -38,10 +38,7 @@ dependencies { implementation project(':PayPalDataCollector') testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation project(':TestUtils') diff --git a/LocalPayment/src/test/java/com/braintreepayments/api/LocalPaymentClientUnitTest.java b/LocalPayment/src/test/java/com/braintreepayments/api/LocalPaymentClientUnitTest.java index 6571eab067..cd2c23a855 100644 --- a/LocalPayment/src/test/java/com/braintreepayments/api/LocalPaymentClientUnitTest.java +++ b/LocalPayment/src/test/java/com/braintreepayments/api/LocalPaymentClientUnitTest.java @@ -6,10 +6,10 @@ import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNull; import static junit.framework.TestCase.assertSame; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -273,7 +273,7 @@ public void startPayment_whenPayPalDisabled_returnsErrorToCallback() { sut.startPayment(request, localPaymentStartCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(Exception.class); - verify(localPaymentStartCallback).onResult((LocalPaymentResult) isNull(), captor.capture()); + verify(localPaymentStartCallback).onResult(isNull(), captor.capture()); Exception exception = captor.getValue(); assertTrue(exception instanceof ConfigurationException); @@ -289,7 +289,7 @@ public void startPayment_whenAmountIsNull_returnsErrorToCallback() { sut.startPayment(request, localPaymentStartCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(Exception.class); - verify(localPaymentStartCallback).onResult((LocalPaymentResult) isNull(), captor.capture()); + verify(localPaymentStartCallback).onResult(isNull(), captor.capture()); Exception exception = captor.getValue(); assertTrue(exception instanceof BraintreeException); @@ -305,7 +305,7 @@ public void startPayment_whenPaymentTypeIsNull_returnsErrorToCallback() { sut.startPayment(request, localPaymentStartCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(Exception.class); - verify(localPaymentStartCallback).onResult((LocalPaymentResult) isNull(), captor.capture()); + verify(localPaymentStartCallback).onResult(isNull(), captor.capture()); Exception exception = captor.getValue(); assertTrue(exception instanceof BraintreeException); @@ -319,7 +319,7 @@ public void startPayment_whenLocalPaymentRequestIsNull_returnsErrorToCallback() sut.startPayment(null, localPaymentStartCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(Exception.class); - verify(localPaymentStartCallback).onResult((LocalPaymentResult) isNull(), captor.capture()); + verify(localPaymentStartCallback).onResult(isNull(), captor.capture()); Exception exception = captor.getValue(); assertTrue(exception instanceof BraintreeException); diff --git a/LocalPayment/src/test/java/com/braintreepayments/api/MockLocalPaymentApiBuilder.java b/LocalPayment/src/test/java/com/braintreepayments/api/MockLocalPaymentApiBuilder.java index 0aaef19794..bc47b0869d 100644 --- a/LocalPayment/src/test/java/com/braintreepayments/api/MockLocalPaymentApiBuilder.java +++ b/LocalPayment/src/test/java/com/braintreepayments/api/MockLocalPaymentApiBuilder.java @@ -1,7 +1,7 @@ package com.braintreepayments.api; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; diff --git a/PayPal/build.gradle b/PayPal/build.gradle index 52d79c9e0f..140dd0d32d 100644 --- a/PayPal/build.gradle +++ b/PayPal/build.gradle @@ -38,10 +38,7 @@ dependencies { implementation project(':PayPalDataCollector') testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation deps.mockitoCore testImplementation project(':TestUtils') diff --git a/PayPal/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java b/PayPal/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java index 570241bcb3..f1ab06cfed 100644 --- a/PayPal/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java +++ b/PayPal/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java @@ -1,14 +1,14 @@ package com.braintreepayments.api; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + import android.content.Context; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; - public class MockPayPalInternalClientBuilder { private Exception error; diff --git a/PayPal/src/test/java/com/braintreepayments/api/PayPalClientUnitTest.java b/PayPal/src/test/java/com/braintreepayments/api/PayPalClientUnitTest.java index bf9d51a1e9..9c402e90df 100644 --- a/PayPal/src/test/java/com/braintreepayments/api/PayPalClientUnitTest.java +++ b/PayPal/src/test/java/com/braintreepayments/api/PayPalClientUnitTest.java @@ -5,9 +5,9 @@ import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNull; import static junit.framework.TestCase.assertSame; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; diff --git a/PayPal/src/test/java/com/braintreepayments/api/PayPalInternalClientUnitTest.java b/PayPal/src/test/java/com/braintreepayments/api/PayPalInternalClientUnitTest.java index e3f376e75f..26df55c84c 100644 --- a/PayPal/src/test/java/com/braintreepayments/api/PayPalInternalClientUnitTest.java +++ b/PayPal/src/test/java/com/braintreepayments/api/PayPalInternalClientUnitTest.java @@ -4,11 +4,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -425,7 +425,7 @@ public void sendRequest_whenRiskCorrelationIdNotNull_setsClientMetadataIdToRiskC sut.sendRequest(context, payPalRequest, payPalInternalClientCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(PayPalResponse.class); - verify(payPalInternalClientCallback).onResult(captor.capture(), (Exception) isNull()); + verify(payPalInternalClientCallback).onResult(captor.capture(), isNull()); PayPalResponse payPalResponse = captor.getValue(); assertEquals("risk-correlation-id", payPalResponse.getClientMetadataId()); diff --git a/PayPalDataCollector/build.gradle b/PayPalDataCollector/build.gradle index 89e1c4bba1..01f097b8e6 100644 --- a/PayPalDataCollector/build.gradle +++ b/PayPalDataCollector/build.gradle @@ -47,10 +47,7 @@ dependencies { testImplementation deps.mockitoCore testImplementation deps.androidxTestCore testImplementation deps.jsonAssert - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation project(':TestUtils') diff --git a/PayPalNativeCheckout/build.gradle b/PayPalNativeCheckout/build.gradle index 374242c6d5..92faa17c38 100644 --- a/PayPalNativeCheckout/build.gradle +++ b/PayPalNativeCheckout/build.gradle @@ -42,11 +42,8 @@ dependencies { } testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading testImplementation deps.jsonAssert + testImplementation deps.mockk testImplementation deps.mockitoCore testImplementation project(':TestUtils') } diff --git a/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClient.java b/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClient.java index a9e855c14f..d2d07fa244 100644 --- a/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClient.java +++ b/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClient.java @@ -3,7 +3,6 @@ import android.content.Context; import android.net.Uri; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.json.JSONException; @@ -20,10 +19,6 @@ class PayPalNativeCheckoutInternalClient { private final String cancelUrl; private final String successUrl; - interface PayPalNativeCheckoutInternalClientCallback { - void onResult(@Nullable PayPalNativeCheckoutResponse payPalResponse, @Nullable Exception error); - } - PayPalNativeCheckoutInternalClient(BraintreeClient braintreeClient) { this(braintreeClient, new PayPalDataCollector(braintreeClient), new ApiClient(braintreeClient)); } diff --git a/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientCallback.java b/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientCallback.java new file mode 100644 index 0000000000..bb6137df3e --- /dev/null +++ b/PayPalNativeCheckout/src/main/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientCallback.java @@ -0,0 +1,12 @@ +package com.braintreepayments.api; + +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; + +/** + * @hide + */ +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +public interface PayPalNativeCheckoutInternalClientCallback { + void onResult(@Nullable PayPalNativeCheckoutResponse payPalResponse, @Nullable Exception error); +} diff --git a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java deleted file mode 100644 index c4c95ba55c..0000000000 --- a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockPayPalInternalClientBuilder.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.braintreepayments.api; - -import android.content.Context; - -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; - -public class MockPayPalInternalClientBuilder { - - private Exception error; - private PayPalNativeCheckoutResponse successResponse; - private PayPalNativeCheckoutAccountNonce tokenizeSuccess; - - public MockPayPalInternalClientBuilder sendRequestSuccess(PayPalNativeCheckoutResponse successResponse) { - this.successResponse = successResponse; - return this; - } - - public MockPayPalInternalClientBuilder sendRequestError(Exception error) { - this.error = error; - return this; - } - - public MockPayPalInternalClientBuilder tokenizeSuccess(PayPalNativeCheckoutAccountNonce tokenizeSuccess) { - this.tokenizeSuccess = tokenizeSuccess; - return this; - } - - public PayPalNativeCheckoutInternalClient build() { - PayPalNativeCheckoutInternalClient payPalInternalClient = mock(PayPalNativeCheckoutInternalClient.class); - - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Exception { - PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback callback = (PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback) invocation.getArguments()[2]; - if (successResponse != null) { - callback.onResult(successResponse, null); - } else if (error != null) { - callback.onResult(null, error); - } - return null; - } - }).when(payPalInternalClient).sendRequest(any(Context.class), any(PayPalNativeRequest.class), any(PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback.class)); - - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) { - PayPalNativeCheckoutResultCallback callback = (PayPalNativeCheckoutResultCallback) invocation.getArguments()[1]; - callback.onResult(tokenizeSuccess, null); - return null; - } - }).when(payPalInternalClient).tokenize(any(PayPalNativeCheckoutAccount.class), any(PayPalNativeCheckoutResultCallback.class)); - - return payPalInternalClient; - } -} diff --git a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockkPayPalInternalClientBuilder.kt b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockkPayPalInternalClientBuilder.kt new file mode 100644 index 0000000000..e83b5920b2 --- /dev/null +++ b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/MockkPayPalInternalClientBuilder.kt @@ -0,0 +1,46 @@ +package com.braintreepayments.api + +import io.mockk.every +import io.mockk.mockk + +internal class MockkPayPalInternalClientBuilder { + + private var error: Exception? = null + private var successResponse: PayPalNativeCheckoutResponse? = null + private var tokenizeSuccess: PayPalNativeCheckoutAccountNonce? = null + + fun sendRequestSuccess(successResponse: PayPalNativeCheckoutResponse): MockkPayPalInternalClientBuilder { + this.successResponse = successResponse + return this + } + + fun sendRequestError(error: Exception): MockkPayPalInternalClientBuilder { + this.error = error + return this + } + + fun tokenizeSuccess(tokenizeSuccess: PayPalNativeCheckoutAccountNonce): MockkPayPalInternalClientBuilder { + this.tokenizeSuccess = tokenizeSuccess + return this + } + + fun build(): PayPalNativeCheckoutInternalClient { + val payPalInternalClient = mockk(relaxed = true) + + every { payPalInternalClient.sendRequest(any(), any(), any()) } answers { + val callback = lastArg() as PayPalNativeCheckoutInternalClientCallback + successResponse?.let { + callback.onResult(it, null) + } ?: error?.let { + callback.onResult(null, it) + } + } + + every { payPalInternalClient.tokenize(any(), any()) } answers { + val callback = lastArg() as PayPalNativeCheckoutResultCallback + callback.onResult(tokenizeSuccess, null) + } + + return payPalInternalClient + } +} \ No newline at end of file diff --git a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.java b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.java deleted file mode 100644 index 20912f641e..0000000000 --- a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.java +++ /dev/null @@ -1,397 +0,0 @@ -package com.braintreepayments.api; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Application; - -import androidx.fragment.app.FragmentActivity; - -import com.paypal.checkout.PayPalCheckout; -import com.paypal.checkout.approve.ApprovalData; -import com.paypal.checkout.approve.OnApprove; -import com.paypal.checkout.cancel.OnCancel; -import com.paypal.checkout.config.CheckoutConfig; -import com.paypal.checkout.config.Environment; -import com.paypal.checkout.config.SettingsConfig; -import com.paypal.checkout.config.UIConfig; -import com.paypal.checkout.error.OnError; -import com.paypal.checkout.shipping.OnShippingChange; -import com.paypal.pyplcheckout.common.instrumentation.PEnums; -import com.paypal.pyplcheckout.common.instrumentation.PLog; - -import org.json.JSONException; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.rule.PowerMockRule; -import org.robolectric.RobolectricTestRunner; - -@RunWith(RobolectricTestRunner.class) -@PowerMockIgnore({"org.powermock.*", "org.mockito.*", "org.robolectric.*", "android.*", "androidx.*"}) -@PrepareForTest({PayPalCheckout.class, PLog.class}) -public class PayPalNativeCheckoutClientUnitTest { - - @Rule - public PowerMockRule powerMockRule = new PowerMockRule(); - - private FragmentActivity activity; - private PayPalNativeCheckoutListener listener; - - private Configuration payPalEnabledConfig; - private Configuration payPalDisabledConfig; - - @Before - public void beforeEach() throws JSONException { - activity = mock(FragmentActivity.class); - listener = mock(PayPalNativeCheckoutListener.class); - - when(activity.getApplication()).thenReturn(mock(Application.class)); - - payPalEnabledConfig = Configuration.fromJson(Fixtures.CONFIGURATION_WITH_LIVE_PAYPAL_NATIVE); - payPalDisabledConfig = Configuration.fromJson(Fixtures.CONFIGURATION_WITH_DISABLED_PAYPAL); - } - - @Test - public void tokenizePayPalAccount_throwsWhenPayPalRequestIsBaseClass() { - PayPalNativeRequest baseRequest = new PayPalNativeRequest() { - @Override - String createRequestBody(Configuration configuration, Authorization authorization, String successUrl, String cancelUrl) throws JSONException { - return null; - } - }; - BraintreeClient braintreeClient = new MockBraintreeClientBuilder().build(); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder().build(); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - - Exception capturedException = null; - try { - sut.tokenizePayPalAccount(activity, baseRequest); - } catch (Exception e) { - capturedException = e; - } - assertNotNull(capturedException); - String expectedMessage = "Unsupported request type. Please use either a " - + "PayPalNativeCheckoutRequest or a PayPalNativeCheckoutVaultRequest."; - assertEquals(expectedMessage, capturedException.getMessage()); - } - - @Test - public void requestBillingAgreement_launchNativeCheckout_sendsAnalyticsEvents() { - PayPalNativeCheckoutVaultRequest payPalVaultRequest = new PayPalNativeCheckoutVaultRequest(); - payPalVaultRequest.setMerchantAccountId("sample-merchant-account-id"); - payPalVaultRequest.setReturnUrl("returnUrl://paypalpay"); - - PayPalNativeCheckoutResponse payPalResponse = new PayPalNativeCheckoutResponse(payPalVaultRequest) - .clientMetadataId("sample-client-metadata-id"); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder() - .sendRequestSuccess(payPalResponse) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - PowerMockito.mockStatic(PayPalCheckout.class); - PowerMockito.mockStatic(PLog.class); - PLog.transition( - PEnums.TransitionName.BRAINTREE_ROUTING, - PEnums.Outcome.THIRD_PARTY, - PEnums.EventCode.E233, - PEnums.StateName.BRAINTREE, - null, - null, - null, - null, - null, - null, - "BrainTree" - ); - PowerMockito.verifyStatic(PLog.class); - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.setListener(listener); - sut.launchNativeCheckout(activity, payPalVaultRequest); - - verify(braintreeClient).sendAnalyticsEvent("paypal-native.tokenize.started"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.tokenize.succeeded"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.billing-agreement.selected"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.billing-agreement.started"); - } - - @Test - public void requestNativeCheckout_returnsErrorFromFailedResponse() { - PayPalNativeCheckoutVaultRequest payPalVaultRequest = new PayPalNativeCheckoutVaultRequest(); - payPalVaultRequest.setMerchantAccountId("sample-merchant-account-id"); - payPalVaultRequest.setReturnUrl("returnUrl://paypalpay"); - - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder() - .sendRequestError(new Exception()) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.setListener(listener); - sut.launchNativeCheckout(activity, payPalVaultRequest); - - verify(listener).onPayPalFailure(any()); - } - - @Test - public void requestOneTimePayment_launchNativeCheckout_sendsAnalyticsEvents() { - PayPalNativeCheckoutRequest payPalCheckoutRequest = new PayPalNativeCheckoutRequest("1.00"); - payPalCheckoutRequest.setIntent("authorize"); - payPalCheckoutRequest.setMerchantAccountId("sample-merchant-account-id"); - payPalCheckoutRequest.setReturnUrl("returnUrl://paypalpay"); - - PayPalNativeCheckoutResponse payPalResponse = new PayPalNativeCheckoutResponse(payPalCheckoutRequest) - .clientMetadataId("sample-client-metadata-id"); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder() - .sendRequestSuccess(payPalResponse) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - - ArgumentCaptor configCaptor = ArgumentCaptor.forClass(CheckoutConfig.class); - ArgumentCaptor onApproveCaptor = ArgumentCaptor.forClass(OnApprove.class); - ArgumentCaptor onShippingChangeCaptor = ArgumentCaptor.forClass(OnShippingChange.class); - ArgumentCaptor onCancelCaptor = ArgumentCaptor.forClass(OnCancel.class); - ArgumentCaptor onErrorCaptor = ArgumentCaptor.forClass(OnError.class); - - PowerMockito.mockStatic(PayPalCheckout.class); - - PayPalCheckout.setConfig( - new CheckoutConfig( - activity.getApplication(), - payPalEnabledConfig.getPayPalClientId(), - Environment.SANDBOX, - null, - null, - null, - new SettingsConfig(), - new UIConfig( - false - ), - "empty" - ) - ); - OnApprove onApprove = approval -> { }; - OnCancel onCancel = () -> { }; - OnError onError = errorInfo -> { }; - - PayPalCheckout.registerCallbacks( - onApprove, - null, - onCancel, - onError - ); - - PowerMockito.verifyStatic(PayPalCheckout.class); - PayPalCheckout.setConfig(configCaptor.capture()); - - PowerMockito.verifyStatic(PayPalCheckout.class); - PayPalCheckout.registerCallbacks(onApproveCaptor.capture(), onShippingChangeCaptor.capture(), onCancelCaptor.capture(), onErrorCaptor.capture()); - - PowerMockito.mockStatic(PLog.class); - PLog.transition( - PEnums.TransitionName.BRAINTREE_ROUTING, - PEnums.Outcome.THIRD_PARTY, - PEnums.EventCode.E233, - PEnums.StateName.BRAINTREE, - null, - null, - null, - null, - null, - null, - "BrainTree" - ); - PowerMockito.verifyStatic(PLog.class); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.setListener(listener); - sut.launchNativeCheckout(activity, payPalCheckoutRequest); - - assertEquals(payPalEnabledConfig.getPayPalClientId(), configCaptor.getValue().getClientId()); - assertEquals(onApprove, onApproveCaptor.getValue()); - assertEquals(onCancel, onCancelCaptor.getValue()); - assertEquals(onError, onErrorCaptor.getValue()); - - verify(braintreeClient).sendAnalyticsEvent("paypal-native.tokenize.started"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.tokenize.succeeded"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.single-payment.selected"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.single-payment.started"); - } - - @Test - public void paypalAccount_isSetupCorrectly() throws JSONException { - String riskCorrelationId = "riskId"; - String sampleMerchantId = "sample-merchant-account-id"; - PayPalNativeCheckoutRequest payPalCheckoutRequest = new PayPalNativeCheckoutRequest("1.00"); - payPalCheckoutRequest.setIntent("authorize"); - payPalCheckoutRequest.setMerchantAccountId(sampleMerchantId); - payPalCheckoutRequest.setReturnUrl("returnUrl://paypalpay"); - payPalCheckoutRequest.setRiskCorrelationId(riskCorrelationId); - - PayPalNativeCheckoutResponse payPalResponse = new PayPalNativeCheckoutResponse(payPalCheckoutRequest) - .clientMetadataId("sample-client-metadata-id"); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder() - .sendRequestSuccess(payPalResponse) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - - ApprovalData approvalData = new ApprovalData(null, null, null, null, null, null, null, null, null); - PayPalNativeCheckoutAccount account = sut.setupAccount(payPalCheckoutRequest, approvalData); - - assertEquals(account.getClientMetadataId(), riskCorrelationId); - assertEquals(account.getMerchantAccountId(), sampleMerchantId); - } - - @Test - public void requestOneTimePayment_sendsBrowserSwitchStartAnalyticsEvent() throws Exception { - PayPalNativeCheckoutRequest payPalCheckoutRequest = new PayPalNativeCheckoutRequest("1.00"); - payPalCheckoutRequest.setIntent("authorize"); - payPalCheckoutRequest.setMerchantAccountId("sample-merchant-account-id"); - payPalCheckoutRequest.setReturnUrl("returnUrl://paypalpay"); - - PayPalNativeCheckoutResponse payPalResponse = new PayPalNativeCheckoutResponse(payPalCheckoutRequest) - .clientMetadataId("sample-client-metadata-id"); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder() - .sendRequestSuccess(payPalResponse) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - PowerMockito.mockStatic(PayPalCheckout.class); - - PowerMockito.mockStatic(PLog.class); - PLog.transition( - PEnums.TransitionName.BRAINTREE_ROUTING, - PEnums.Outcome.THIRD_PARTY, - PEnums.EventCode.E233, - PEnums.StateName.BRAINTREE, - null, - null, - null, - null, - null, - null, - "BrainTree" - ); - PowerMockito.verifyStatic(PLog.class); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.setListener(listener); - sut.launchNativeCheckout(activity, payPalCheckoutRequest); - - verify(braintreeClient).sendAnalyticsEvent("paypal-native.single-payment.selected"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.single-payment.started"); - } - - @Test - public void requestOneTimePayment_sendsPayPalPayLaterOfferedAnalyticsEvent() throws Exception { - BraintreeClient braintreeClient = new MockBraintreeClientBuilder().build(); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder().build(); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - PayPalNativeCheckoutRequest request = new PayPalNativeCheckoutRequest("1.00"); - request.setShouldOfferPayLater(true); - sut.tokenizePayPalAccount(activity, request); - - verify(braintreeClient).sendAnalyticsEvent("paypal-native.single-payment.paylater.offered"); - } - - @Test - public void tokenizePayPalAccount_sendsPayPalRequestViaInternalClient() throws Exception { - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder().build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - - PayPalNativeCheckoutVaultRequest payPalRequest = new PayPalNativeCheckoutVaultRequest(); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.tokenizePayPalAccount(activity, payPalRequest); - - verify(payPalInternalClient).sendRequest(same(activity), same(payPalRequest), any(PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback.class)); - } - - @Test - public void requestOneTimePayment_sendsPayPalRequestViaInternalClient() throws Exception { - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder().build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(payPalEnabledConfig) - .build(); - - PayPalNativeCheckoutRequest payPalRequest = new PayPalNativeCheckoutRequest("1.00"); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.tokenizePayPalAccount(activity, payPalRequest); - - verify(payPalInternalClient).sendRequest(same(activity), same(payPalRequest), any(PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback.class)); - } - - @Test - public void tokenizePayPalAccount_sendsPayPalCreditOfferedAnalyticsEvent() throws Exception { - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder().build(); - BraintreeClient braintreeClient = new MockBraintreeClientBuilder().build(); - - PayPalNativeCheckoutVaultRequest payPalRequest = new PayPalNativeCheckoutVaultRequest(); - payPalRequest.setShouldOfferCredit(true); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.tokenizePayPalAccount(activity, payPalRequest); - - verify(braintreeClient).sendAnalyticsEvent("paypal-native.billing-agreement.credit.offered"); - } - - @Test - public void launchNativeCheckout_notifiesErrorWhenPayPalRequestIsBaseClass_sendsAnalyticsEvents() { - PayPalNativeRequest baseRequest = new PayPalNativeRequest() { - @Override - String createRequestBody(Configuration configuration, Authorization authorization, String successUrl, String cancelUrl) throws JSONException { - return null; - } - }; - BraintreeClient braintreeClient = new MockBraintreeClientBuilder().build(); - PayPalNativeCheckoutInternalClient payPalInternalClient = new MockPayPalInternalClientBuilder().build(); - - PayPalNativeCheckoutClient sut = new PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient); - sut.setListener(listener); - - sut.launchNativeCheckout(activity, baseRequest); - - ArgumentCaptor captor = ArgumentCaptor.forClass(Exception.class); - verify(listener).onPayPalFailure(captor.capture()); - - Exception capturedException = captor.getValue(); - String expectedMessage = "Unsupported request type. Please use either a " - + "PayPalNativeCheckoutRequest or a PayPalNativeCheckoutVaultRequest."; - assertEquals(expectedMessage, capturedException.getMessage()); - - verify(braintreeClient).sendAnalyticsEvent("paypal-native.tokenize.started"); - verify(braintreeClient).sendAnalyticsEvent("paypal-native.tokenize.invalid-request.failed"); - } -} \ No newline at end of file diff --git a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.kt b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.kt new file mode 100644 index 0000000000..a483f53201 --- /dev/null +++ b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutClientUnitTest.kt @@ -0,0 +1,374 @@ +package com.braintreepayments.api + +import android.app.Application +import androidx.fragment.app.FragmentActivity +import com.braintreepayments.api.Configuration.Companion.fromJson +import com.paypal.checkout.PayPalCheckout +import com.paypal.checkout.approve.Approval +import com.paypal.checkout.approve.ApprovalData +import com.paypal.checkout.approve.OnApprove +import com.paypal.checkout.cancel.OnCancel +import com.paypal.checkout.config.CheckoutConfig +import com.paypal.checkout.config.Environment +import com.paypal.checkout.config.SettingsConfig +import com.paypal.checkout.config.UIConfig +import com.paypal.checkout.error.ErrorInfo +import com.paypal.checkout.error.OnError +import com.paypal.checkout.shipping.OnShippingChange +import com.paypal.pyplcheckout.common.instrumentation.PEnums +import com.paypal.pyplcheckout.common.instrumentation.PEnums.EventCode +import com.paypal.pyplcheckout.common.instrumentation.PEnums.StateName +import com.paypal.pyplcheckout.common.instrumentation.PEnums.TransitionName +import com.paypal.pyplcheckout.common.instrumentation.PLog +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.slot +import io.mockk.verify +import junit.framework.TestCase.assertEquals +import junit.framework.TestCase.assertNotNull +import org.json.JSONException +import org.junit.Before +import org.junit.Ignore +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class PayPalNativeCheckoutClientUnitTest { + + private lateinit var activity: FragmentActivity + private lateinit var application: Application + private lateinit var listener: PayPalNativeCheckoutListener + private lateinit var payPalEnabledConfig: Configuration + private lateinit var payPalDisabledConfig: Configuration + + @Before + @Throws(JSONException::class) + fun beforeEach() { + mockkStatic(PayPalCheckout::class) + mockkStatic(PLog::class) + + activity = mockk(relaxed = true) + listener = mockk(relaxed = true) + + application = mockk(relaxed = true) + every { activity.application } returns application + + payPalEnabledConfig = fromJson(Fixtures.CONFIGURATION_WITH_LIVE_PAYPAL_NATIVE) + payPalDisabledConfig = fromJson(Fixtures.CONFIGURATION_WITH_DISABLED_PAYPAL) + } + + @Test + fun tokenizePayPalAccount_throwsWhenPayPalRequestIsBaseClass() { + val baseRequest: PayPalNativeRequest = object : PayPalNativeRequest() { + @Throws(JSONException::class) + public override fun createRequestBody( + configuration: Configuration, + authorization: Authorization, + successUrl: String, + cancelUrl: String + ): String = "" + } + + val braintreeClient = MockkBraintreeClientBuilder().build() + val payPalInternalClient = MockkPayPalInternalClientBuilder().build() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + var capturedException: Exception? = null + try { + sut.tokenizePayPalAccount(activity, baseRequest) + } catch (e: Exception) { + capturedException = e + } + assertNotNull(capturedException) + val expectedMessage = ("Unsupported request type. Please use either a " + + "PayPalNativeCheckoutRequest or a PayPalNativeCheckoutVaultRequest.") + assertEquals(expectedMessage, capturedException!!.message) + } + + @Test + @Ignore("Refactor test to work with mockk") + fun requestBillingAgreement_launchNativeCheckout_sendsAnalyticsEvents() { + val payPalVaultRequest = PayPalNativeCheckoutVaultRequest() + payPalVaultRequest.merchantAccountId = "sample-merchant-account-id" + payPalVaultRequest.returnUrl = "returnUrl://paypalpay" + val payPalResponse = PayPalNativeCheckoutResponse(payPalVaultRequest) + .clientMetadataId("sample-client-metadata-id") + val payPalInternalClient = MockkPayPalInternalClientBuilder() + .sendRequestSuccess(payPalResponse) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.setListener(listener) + sut.launchNativeCheckout(activity, payPalVaultRequest) + + verify { + PLog.transition( + TransitionName.BRAINTREE_ROUTING, + PEnums.Outcome.THIRD_PARTY, + EventCode.E233, + StateName.BRAINTREE, + null, + null, + null, + null, + null, + null, + "BrainTree" + ) + } + + verify { braintreeClient.sendAnalyticsEvent("paypal-native.tokenize.started") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.tokenize.succeeded") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.billing-agreement.selected") } + } + + @Test + fun requestNativeCheckout_returnsErrorFromFailedResponse() { + val payPalVaultRequest = PayPalNativeCheckoutVaultRequest() + payPalVaultRequest.merchantAccountId = "sample-merchant-account-id" + payPalVaultRequest.returnUrl = "returnUrl://paypalpay" + val payPalInternalClient = MockkPayPalInternalClientBuilder() + .sendRequestError(Exception()) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.setListener(listener) + sut.launchNativeCheckout(activity, payPalVaultRequest) + every { listener.onPayPalFailure(any()) } + } + + @Test + @Ignore("Refactor test to work with mockk") + fun requestOneTimePayment_launchNativeCheckout_sendsAnalyticsEvents() { + val payPalCheckoutRequest = PayPalNativeCheckoutRequest("1.00") + payPalCheckoutRequest.intent = "authorize" + payPalCheckoutRequest.merchantAccountId = "sample-merchant-account-id" + payPalCheckoutRequest.returnUrl = "returnUrl://paypalpay" + val payPalResponse = PayPalNativeCheckoutResponse(payPalCheckoutRequest) + .clientMetadataId("sample-client-metadata-id") + val payPalInternalClient = MockkPayPalInternalClientBuilder() + .sendRequestSuccess(payPalResponse) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + val configSlot = slot() + val onApproveSlot = slot() + val onShippingChangeSlot = slot() + val onCancelSlot = slot() + val onErrorSlot = slot() + + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.setListener(listener) + sut.launchNativeCheckout(activity, payPalCheckoutRequest) + + verify { + PayPalCheckout.setConfig( + CheckoutConfig( + application, + payPalEnabledConfig.payPalClientId!!, Environment.SANDBOX, + null, + null, + null, + SettingsConfig(), + UIConfig( + false + ), + "empty" + ) + ) + } + + val onApprove = OnApprove { approval: Approval? -> } + val onCancel = OnCancel {} + val onError = OnError { errorInfo: ErrorInfo? -> } + PayPalCheckout.registerCallbacks( + onApprove, + null, + onCancel, + onError + ) + + verify { PayPalCheckout.setConfig(capture(configSlot)) } + verify { + PayPalCheckout.registerCallbacks( + capture(onApproveSlot), + capture(onShippingChangeSlot), + capture(onCancelSlot), + capture(onErrorSlot) + ) + } + + verify { + PLog.transition( + TransitionName.BRAINTREE_ROUTING, + PEnums.Outcome.THIRD_PARTY, + EventCode.E233, + StateName.BRAINTREE, + null, + null, + null, + null, + null, + null, + "BrainTree" + ) + } + + assertEquals(payPalEnabledConfig.payPalClientId, configSlot.captured.clientId) + assertEquals(onApprove, onApproveSlot.captured) + assertEquals(onCancel, onCancelSlot.captured) + assertEquals(onError, onErrorSlot.captured) + + verify { braintreeClient.sendAnalyticsEvent("paypal-native.tokenize.started") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.tokenize.succeeded") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.single-payment.selected") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.single-payment.started") } + } + + @Test + @Throws(JSONException::class) + fun paypalAccount_isSetupCorrectly() { + val riskCorrelationId = "riskId" + val sampleMerchantId = "sample-merchant-account-id" + val payPalCheckoutRequest = PayPalNativeCheckoutRequest("1.00") + payPalCheckoutRequest.intent = "authorize" + payPalCheckoutRequest.merchantAccountId = sampleMerchantId + payPalCheckoutRequest.returnUrl = "returnUrl://paypalpay" + payPalCheckoutRequest.riskCorrelationId = riskCorrelationId + val payPalResponse = PayPalNativeCheckoutResponse(payPalCheckoutRequest) + .clientMetadataId("sample-client-metadata-id") + val payPalInternalClient = MockkPayPalInternalClientBuilder() + .sendRequestSuccess(payPalResponse) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + val approvalData = ApprovalData(null, null, null, null, null, null, null, null, null) + val account = sut.setupAccount(payPalCheckoutRequest, approvalData) + assertEquals(account.clientMetadataId, riskCorrelationId) + assertEquals(account.merchantAccountId, sampleMerchantId) + } + + @Test + @Throws(Exception::class) + @Ignore("Refactor test to work with mockk") + fun requestOneTimePayment_sendsBrowserSwitchStartAnalyticsEvent() { + val payPalCheckoutRequest = PayPalNativeCheckoutRequest("1.00") + payPalCheckoutRequest.intent = "authorize" + payPalCheckoutRequest.merchantAccountId = "sample-merchant-account-id" + payPalCheckoutRequest.returnUrl = "returnUrl://paypalpay" + val payPalResponse = PayPalNativeCheckoutResponse(payPalCheckoutRequest) + .clientMetadataId("sample-client-metadata-id") + val payPalInternalClient = MockkPayPalInternalClientBuilder() + .sendRequestSuccess(payPalResponse) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.setListener(listener) + sut.launchNativeCheckout(activity, payPalCheckoutRequest) + + verify { + PLog.transition( + TransitionName.BRAINTREE_ROUTING, + PEnums.Outcome.THIRD_PARTY, + EventCode.E233, + StateName.BRAINTREE, + null, + null, + null, + null, + null, + null, + "BrainTree" + ) + } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.single-payment.selected") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.single-payment.started") } + } + + @Test + @Throws(Exception::class) + fun requestOneTimePayment_sendsPayPalPayLaterOfferedAnalyticsEvent() { + val braintreeClient = MockkBraintreeClientBuilder().build() + val payPalInternalClient = MockkPayPalInternalClientBuilder().build() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + val request = PayPalNativeCheckoutRequest("1.00") + request.shouldOfferPayLater = true + sut.tokenizePayPalAccount(activity, request) + verify { braintreeClient.sendAnalyticsEvent("paypal-native.single-payment.paylater.offered") } + } + + @Test + @Throws(Exception::class) + fun tokenizePayPalAccount_sendsPayPalRequestViaInternalClient() { + val payPalInternalClient = MockkPayPalInternalClientBuilder().build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + val payPalRequest = PayPalNativeCheckoutVaultRequest() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.tokenizePayPalAccount(activity, payPalRequest) + verify { payPalInternalClient.sendRequest(activity, payPalRequest, any()) } + } + + @Test + @Throws(Exception::class) + fun requestOneTimePayment_sendsPayPalRequestViaInternalClient() { + val payPalInternalClient = MockkPayPalInternalClientBuilder().build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(payPalEnabledConfig) + .build() + val payPalRequest = PayPalNativeCheckoutRequest("1.00") + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.tokenizePayPalAccount(activity, payPalRequest) + verify { payPalInternalClient.sendRequest(activity, payPalRequest, any()) } + } + + @Test + @Throws(Exception::class) + fun tokenizePayPalAccount_sendsPayPalCreditOfferedAnalyticsEvent() { + val payPalInternalClient = MockkPayPalInternalClientBuilder().build() + val braintreeClient = MockkBraintreeClientBuilder().build() + val payPalRequest = PayPalNativeCheckoutVaultRequest() + payPalRequest.shouldOfferCredit = true + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.tokenizePayPalAccount(activity, payPalRequest) + verify { braintreeClient.sendAnalyticsEvent("paypal-native.billing-agreement.credit.offered") } + } + + @Test + fun launchNativeCheckout_notifiesErrorWhenPayPalRequestIsBaseClass_sendsAnalyticsEvents() { + val baseRequest: PayPalNativeRequest = object : PayPalNativeRequest() { + @Throws(JSONException::class) + public override fun createRequestBody( + configuration: Configuration, + authorization: Authorization, + successUrl: String, + cancelUrl: String + ): String = "" + } + val braintreeClient = MockkBraintreeClientBuilder().build() + val payPalInternalClient = MockkPayPalInternalClientBuilder().build() + val sut = PayPalNativeCheckoutClient(braintreeClient, payPalInternalClient) + sut.setListener(listener) + sut.launchNativeCheckout(activity, baseRequest) + val exceptionSlot = slot() + verify { listener.onPayPalFailure(capture(exceptionSlot)) } + val capturedException = exceptionSlot.captured + val expectedMessage = ("Unsupported request type. Please use either a " + + "PayPalNativeCheckoutRequest or a PayPalNativeCheckoutVaultRequest.") + assertEquals(expectedMessage, capturedException.message) + verify { braintreeClient.sendAnalyticsEvent("paypal-native.tokenize.started") } + verify { braintreeClient.sendAnalyticsEvent("paypal-native.tokenize.invalid-request.failed") } + } +} \ No newline at end of file diff --git a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientUnitTest.java b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientUnitTest.java index 6e64ab4780..5137010b02 100644 --- a/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientUnitTest.java +++ b/PayPalNativeCheckout/src/test/java/com/braintreepayments/api/PayPalNativeCheckoutInternalClientUnitTest.java @@ -1,6 +1,17 @@ package com.braintreepayments.api; import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Context; @@ -17,18 +28,6 @@ import java.util.ArrayList; import java.util.Collections; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(RobolectricTestRunner.class) public class PayPalNativeCheckoutInternalClientUnitTest { @@ -41,7 +40,7 @@ public class PayPalNativeCheckoutInternalClientUnitTest { private PayPalDataCollector payPalDataCollector; private ApiClient apiClient; - PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback payPalInternalClientCallback; + PayPalNativeCheckoutInternalClientCallback payPalInternalClientCallback; @Before public void beforeEach() { @@ -52,7 +51,7 @@ public void beforeEach() { payPalDataCollector = mock(PayPalDataCollector.class); apiClient = mock(ApiClient.class); - payPalInternalClientCallback = mock(PayPalNativeCheckoutInternalClient.PayPalNativeCheckoutInternalClientCallback.class); + payPalInternalClientCallback = mock(PayPalNativeCheckoutInternalClientCallback.class); } @Test diff --git a/PayPalNativeCheckout/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/PayPalNativeCheckout/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..ca6ee9cea8 --- /dev/null +++ b/PayPalNativeCheckout/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/PayPalNativeCheckout/src/test/resources/org/powermock/extensions/configuration.properties b/PayPalNativeCheckout/src/test/resources/org/powermock/extensions/configuration.properties deleted file mode 100644 index 4734ad10dd..0000000000 --- a/PayPalNativeCheckout/src/test/resources/org/powermock/extensions/configuration.properties +++ /dev/null @@ -1,2 +0,0 @@ -mockito.mock-maker-class=mock-maker-inline - diff --git a/SEPADirectDebit/build.gradle b/SEPADirectDebit/build.gradle index 5b589f5f94..c21a224b62 100644 --- a/SEPADirectDebit/build.gradle +++ b/SEPADirectDebit/build.gradle @@ -38,10 +38,7 @@ dependencies { testImplementation deps.robolectric testImplementation deps.junitTest - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation project(':TestUtils') androidTestImplementation project(':TestUtils') diff --git a/SEPADirectDebit/src/test/java/com/braintreepayments/api/SEPADirectDebitApiUnitTest.java b/SEPADirectDebit/src/test/java/com/braintreepayments/api/SEPADirectDebitApiUnitTest.java index 14ac868ce4..0e0a2244df 100644 --- a/SEPADirectDebit/src/test/java/com/braintreepayments/api/SEPADirectDebitApiUnitTest.java +++ b/SEPADirectDebit/src/test/java/com/braintreepayments/api/SEPADirectDebitApiUnitTest.java @@ -5,8 +5,8 @@ import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.mock; import org.json.JSONException; import org.junit.Before; diff --git a/SamsungPay/build.gradle b/SamsungPay/build.gradle index c9a75225e0..0df3abfbb0 100644 --- a/SamsungPay/build.gradle +++ b/SamsungPay/build.gradle @@ -45,10 +45,7 @@ dependencies { testImplementation deps.robolectric testImplementation deps.junitTest - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation project(':TestUtils') } diff --git a/SharedUtils/build.gradle b/SharedUtils/build.gradle index 38c9a67e09..d664250a61 100644 --- a/SharedUtils/build.gradle +++ b/SharedUtils/build.gradle @@ -41,11 +41,7 @@ dependencies { testImplementation deps.androidxTestCore testImplementation deps.mockitoCore testImplementation deps.robolectric - - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore androidTestImplementation deps.androidxTestRunner androidTestImplementation deps.junitTest diff --git a/SharedUtils/src/test/java/com/braintreepayments/api/HttpClientUnitTest.java b/SharedUtils/src/test/java/com/braintreepayments/api/HttpClientUnitTest.java index 6fa516cb84..090e0ae6e8 100644 --- a/SharedUtils/src/test/java/com/braintreepayments/api/HttpClientUnitTest.java +++ b/SharedUtils/src/test/java/com/braintreepayments/api/HttpClientUnitTest.java @@ -1,9 +1,5 @@ package com.braintreepayments.api; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; - import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.isNull; @@ -13,9 +9,13 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + public class HttpClientUnitTest { private SynchronousHttpClient syncHttpClient; @@ -38,7 +38,7 @@ public void sendRequest_sendsRequestOnBackgroundThread() throws Exception { HttpResponseCallback callback = mock(HttpResponseCallback.class); sut.sendRequest(httpRequest, callback); - verifyZeroInteractions(syncHttpClient); + verifyNoInteractions(syncHttpClient); threadScheduler.flushBackgroundThread(); verify(syncHttpClient).request(httpRequest); diff --git a/SharedUtils/src/test/java/com/braintreepayments/api/SynchronousHttpClientUnitTest.java b/SharedUtils/src/test/java/com/braintreepayments/api/SynchronousHttpClientUnitTest.java index 3a22d89445..54b53d1ee8 100644 --- a/SharedUtils/src/test/java/com/braintreepayments/api/SynchronousHttpClientUnitTest.java +++ b/SharedUtils/src/test/java/com/braintreepayments/api/SynchronousHttpClientUnitTest.java @@ -2,18 +2,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; import org.junit.Before; import org.junit.Test; import org.junit.function.ThrowingRunnable; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.OutputStream; import java.net.HttpURLConnection; @@ -25,8 +22,6 @@ import javax.net.ssl.SSLException; import javax.net.ssl.SSLSocketFactory; -@RunWith(PowerMockRunner.class) -@PrepareForTest({ TLSSocketFactory.class }) public class SynchronousHttpClientUnitTest { BaseHttpResponseParser httpResponseParser; @@ -34,7 +29,6 @@ public class SynchronousHttpClientUnitTest { @Before public void beforeEach() { - mockStatic(TLSSocketFactory.class); httpResponseParser = mock(BaseHttpResponseParser.class); sslSocketFactory = mock(SSLSocketFactory.class); } @@ -108,12 +102,9 @@ public void request_whenConnectionIsHttps_usesDefaultSSLSocketFactoryWhenNoFacto when(connection.getResponseCode()).thenReturn(200); when(httpResponseParser.parse(200, connection)).thenReturn("http_ok"); - TLSSocketFactory defaultSocketFactory = mock(TLSSocketFactory.class); - when(TLSSocketFactory.newInstance()).thenReturn(defaultSocketFactory); - SynchronousHttpClient sut = new SynchronousHttpClient(null, httpResponseParser); sut.request(httpRequest); - verify(connection).setSSLSocketFactory(defaultSocketFactory); + verify(connection).setSSLSocketFactory(any(TLSSocketFactory.class)); } @Test @@ -153,9 +144,6 @@ public void request_whenConnectionIsHttps_andSSLSocketFactoryIsNull_throwsSSLExc when(connection.getResponseCode()).thenReturn(200); when(httpResponseParser.parse(200, connection)).thenReturn("http_ok"); - TLSSocketFactory defaultSocketFactory = mock(TLSSocketFactory.class); - when(TLSSocketFactory.newInstance()).thenReturn(defaultSocketFactory); - final SynchronousHttpClient sut = new SynchronousHttpClient(null, httpResponseParser); sut.setSSLSocketFactory(null); SSLException exception = assertThrows(SSLException.class, new ThrowingRunnable() { diff --git a/TestUtils/build.gradle b/TestUtils/build.gradle index fe84b24219..acefea4635 100644 --- a/TestUtils/build.gradle +++ b/TestUtils/build.gradle @@ -33,12 +33,9 @@ dependencies { implementation deps.junitTest compileOnly deps.robolectric - compileOnly deps.powermockJunit - compileOnly deps.powermockRule - compileOnly deps.powermockMockito - compileOnly deps.powermockClassloading compileOnly deps.jsonAssert compileOnly deps.mockk + compileOnly deps.mockitoCore implementation project(':BraintreeCore') implementation project(':ThreeDSecure') diff --git a/TestUtils/src/main/java/com/braintreepayments/api/MockApiClientBuilder.java b/TestUtils/src/main/java/com/braintreepayments/api/MockApiClientBuilder.java index 6f97207aa1..00f824dd67 100644 --- a/TestUtils/src/main/java/com/braintreepayments/api/MockApiClientBuilder.java +++ b/TestUtils/src/main/java/com/braintreepayments/api/MockApiClientBuilder.java @@ -1,13 +1,13 @@ package com.braintreepayments.api; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + import org.json.JSONObject; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; - public class MockApiClientBuilder { private Exception tokenizeRESTError; diff --git a/TestUtils/src/main/java/com/braintreepayments/api/MockBraintreeClientBuilder.java b/TestUtils/src/main/java/com/braintreepayments/api/MockBraintreeClientBuilder.java index 49c6a557fa..d064997c7d 100644 --- a/TestUtils/src/main/java/com/braintreepayments/api/MockBraintreeClientBuilder.java +++ b/TestUtils/src/main/java/com/braintreepayments/api/MockBraintreeClientBuilder.java @@ -1,8 +1,8 @@ package com.braintreepayments.api; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -12,7 +12,6 @@ import androidx.fragment.app.FragmentActivity; -import org.mockito.ArgumentMatchers; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -145,11 +144,7 @@ public Void answer(InvocationOnMock invocation) { } }).when(braintreeClient).getAuthorization(any(AuthorizationCallback.class)); - // HACK: some google pay tests fail when getReturnUrlScheme is stubbed but not invoked - // TODO: create a wrapper around google wallet api to avoid having to use Powermock and Robolectric at the same time, which seems to be causing this issue - if (returnUrlScheme != null) { - when(braintreeClient.getReturnUrlScheme()).thenReturn(returnUrlScheme); - } + when(braintreeClient.getReturnUrlScheme()).thenReturn(returnUrlScheme); if (browserSwitchAssertionError != null) { try { @@ -158,7 +153,7 @@ public Void answer(InvocationOnMock invocation) { } catch (BrowserSwitchException ignored) {} } - when(braintreeClient.getManifestActivityInfo(ArgumentMatchers.any())).thenReturn(activityInfo); + when(braintreeClient.getManifestActivityInfo(any())).thenReturn(activityInfo); when(braintreeClient.deliverBrowserSwitchResult(any(FragmentActivity.class))).thenReturn(browserSwitchResult); when(braintreeClient.launchesBrowserSwitchAsNewTask()).thenReturn(launchesBrowserSwitchAsNewTask); diff --git a/TestUtils/src/main/java/com/braintreepayments/api/MockkApiClientBuilder.kt b/TestUtils/src/main/java/com/braintreepayments/api/MockkApiClientBuilder.kt new file mode 100644 index 0000000000..7332b592c7 --- /dev/null +++ b/TestUtils/src/main/java/com/braintreepayments/api/MockkApiClientBuilder.kt @@ -0,0 +1,50 @@ +package com.braintreepayments.api + +import io.mockk.every +import io.mockk.mockk +import org.json.JSONObject + +class MockkApiClientBuilder { + + private var tokenizeRESTError: Exception? = null + private var tokenizeRESTSuccess: JSONObject? = null + + private var tokenizeGraphQLError: Exception? = null + private var tokenizeGraphQLSuccess: JSONObject? = null + + fun tokenizeRESTError(tokenizeRestError: Exception): MockkApiClientBuilder { + tokenizeRESTError = tokenizeRestError + return this + } + + fun tokenizeRESTSuccess(tokenizeRestSuccess: JSONObject): MockkApiClientBuilder { + tokenizeRESTSuccess = tokenizeRestSuccess + return this + } + + fun tokenizeGraphQLError(tokenizeGraphQLError: Exception): MockkApiClientBuilder { + this.tokenizeGraphQLError = tokenizeGraphQLError + return this + } + + fun tokenizeGraphQLSuccess(tokenizeGraphQLSuccess: JSONObject): MockkApiClientBuilder { + this.tokenizeGraphQLSuccess = tokenizeGraphQLSuccess + return this + } + + fun build(): ApiClient { + val apiClient = mockk(relaxed = true) + + every { apiClient.tokenizeREST(any(), any())} answers { + val listener = lastArg() as TokenizeCallback + listener.onResult(tokenizeRESTSuccess, tokenizeRESTError) + } + + every { apiClient.tokenizeGraphQL(any(), any())} answers { + val listener = lastArg() as TokenizeCallback + listener.onResult(tokenizeGraphQLSuccess, tokenizeGraphQLError) + } + return apiClient + } + +} \ No newline at end of file diff --git a/ThreeDSecure/build.gradle b/ThreeDSecure/build.gradle index c0537d07e2..63c21f358d 100644 --- a/ThreeDSecure/build.gradle +++ b/ThreeDSecure/build.gradle @@ -40,20 +40,18 @@ dependencies { implementation deps.appCompat implementation deps.lifecycleRuntime + testImplementation deps.robolectric + testImplementation deps.mockk + testImplementation deps.mockitoCore + testImplementation deps.jsonAssert + testImplementation deps.androidxTestCore + testImplementation project(':TestUtils') + androidTestImplementation deps.dexmakerMockito androidTestImplementation deps.androidxTestRules androidTestImplementation deps.androidxTestRunner androidTestImplementation deps.junitTest androidTestImplementation project(':TestUtils') - - testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading - testImplementation deps.jsonAssert - testImplementation deps.androidxTestCore - testImplementation project(':TestUtils') } // region signing and publishing diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.java deleted file mode 100644 index 185fd045a2..0000000000 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.java +++ /dev/null @@ -1,284 +0,0 @@ -package com.braintreepayments.api; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; - -import android.app.Activity; -import android.content.Context; - -import androidx.fragment.app.FragmentActivity; - -import com.cardinalcommerce.cardinalmobilesdk.Cardinal; -import com.cardinalcommerce.cardinalmobilesdk.enums.CardinalEnvironment; -import com.cardinalcommerce.cardinalmobilesdk.enums.CardinalRenderType; -import com.cardinalcommerce.cardinalmobilesdk.enums.CardinalUiType; -import com.cardinalcommerce.cardinalmobilesdk.models.CardinalConfigurationParameters; -import com.cardinalcommerce.cardinalmobilesdk.services.CardinalInitService; -import com.cardinalcommerce.cardinalmobilesdk.services.CardinalValidateReceiver; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.ArrayList; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({Cardinal.class}) -public class CardinalClientUnitTest { - - private Cardinal cardinalInstance; - - private FragmentActivity activity; - private Configuration configuration; - - private Context context; - private CardinalInitializeCallback cardinalInitializeCallback; - private CardinalValidateReceiver cardinalValidateReceiver; - - @Before - public void beforeEach() { - mockStatic(Cardinal.class); - context = mock(Context.class); - configuration = mock(Configuration.class); - cardinalInitializeCallback = mock(CardinalInitializeCallback.class); - cardinalInstance = mock(Cardinal.class); - - activity = mock(FragmentActivity.class); - cardinalValidateReceiver = mock(CardinalValidateReceiver.class); - } - - @Test - public void initialize_configuresDefaultCardinalConfigurationParameters() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalConfigurationParameters.class); - verify(cardinalInstance).configure(same(context), captor.capture()); - - CardinalConfigurationParameters parameters = captor.getValue(); - assertEquals(CardinalEnvironment.STAGING, parameters.getEnvironment()); - assertEquals(8000, parameters.getRequestTimeout()); - assertTrue(parameters.isEnableDFSync()); - } - - @Test - public void initialize_whenV2UiCustomizationNotNull_setsCardinalConfigurationParameters() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureV2UiCustomization v2UiCustomization = new ThreeDSecureV2UiCustomization(); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - request.setV2UiCustomization(v2UiCustomization); - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalConfigurationParameters.class); - verify(cardinalInstance).configure(same(context), captor.capture()); - - CardinalConfigurationParameters parameters = captor.getValue(); - assertEquals(request.getV2UiCustomization().getCardinalUiCustomization(), parameters.getUICustomization()); - } - - @Test - public void initialize_whenEnvironmentProduction_configuresCardinalEnvironmentProduction() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - when(configuration.getEnvironment()).thenReturn("production"); - - CardinalClient sut = new CardinalClient(); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalConfigurationParameters.class); - verify(cardinalInstance).configure(same(context), captor.capture()); - - CardinalConfigurationParameters parameters = captor.getValue(); - assertEquals(CardinalEnvironment.PRODUCTION, parameters.getEnvironment()); - } - - @Test - public void initialize_whenUiTypeNotNull_setsCardinalConfigurationParameters() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - request.setUiType(ThreeDSecureRequest.BOTH); - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalConfigurationParameters.class); - verify(cardinalInstance).configure(same(context), captor.capture()); - - CardinalConfigurationParameters parameters = captor.getValue(); - assertEquals(CardinalUiType.BOTH, parameters.getUiType()); - } - - @Test - public void initialize_whenRenderTypeNotNull_setsCardinalConfigurationParameters() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - CardinalClient sut = new CardinalClient(); - - ArrayList renderTypes = new ArrayList<>(); - renderTypes.add(ThreeDSecureRequest.OTP); - renderTypes.add(ThreeDSecureRequest.SINGLE_SELECT); - renderTypes.add(ThreeDSecureRequest.MULTI_SELECT); - renderTypes.add(ThreeDSecureRequest.OOB); - renderTypes.add(ThreeDSecureRequest.RENDER_HTML); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - request.setRenderTypes(renderTypes); - - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalConfigurationParameters.class); - verify(cardinalInstance).configure(same(context), captor.capture()); - - CardinalConfigurationParameters parameters = captor.getValue(); - assertEquals(5, parameters.getRenderType().length()); - } - - @Test - public void initialize_returnsConsumerSessionIdToListener() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - when(configuration.getCardinalAuthenticationJwt()).thenReturn("token"); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalInitService.class); - verify(cardinalInstance).init(eq("token"), captor.capture()); - - CardinalInitService cardinalInitService = captor.getValue(); - cardinalInitService.onSetupCompleted("session-id"); - - verify(cardinalInitializeCallback).onResult(sut.getConsumerSessionId(), null); - assertEquals("session-id", sut.getConsumerSessionId()); - } - - @Test - public void initialize_whenConsumerSessionIdIsNull_returnsBraintreeExceptionToListener() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - when(configuration.getCardinalAuthenticationJwt()).thenReturn("token"); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - sut.initialize(context, configuration, request, cardinalInitializeCallback); - - ArgumentCaptor captor = ArgumentCaptor.forClass(CardinalInitService.class); - verify(cardinalInstance).init(eq("token"), captor.capture()); - - CardinalInitService cardinalInitService = captor.getValue(); - cardinalInitService.onValidated(null, null); - - ArgumentCaptor exceptionCaptor = ArgumentCaptor.forClass(BraintreeException.class); - verify(cardinalInitializeCallback).onResult(isNull(String.class), exceptionCaptor.capture()); - assertEquals(exceptionCaptor.getValue().getMessage(), "consumer session id not available"); - } - - @Test - public void initialize_onCardinalConfigureRuntimeException_throwsError() { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - when(configuration.getCardinalAuthenticationJwt()).thenReturn("token"); - CardinalClient sut = new CardinalClient(); - - RuntimeException runtimeException = new RuntimeException("fake message"); - doThrow(runtimeException) - .when(cardinalInstance) - .configure(any(Context.class), any(CardinalConfigurationParameters.class)); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - - try { - sut.initialize(context, configuration, request, cardinalInitializeCallback); - fail("should not get here"); - } catch (BraintreeException e) { - assertEquals("Cardinal SDK configure Error.", e.getMessage()); - assertSame(runtimeException, e.getCause()); - } - } - - @Test - public void initialize_onCardinalInitRuntimeException_throwsError() { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - when(configuration.getCardinalAuthenticationJwt()).thenReturn("token"); - CardinalClient sut = new CardinalClient(); - - RuntimeException runtimeException = new RuntimeException("fake message"); - doThrow(runtimeException) - .when(cardinalInstance) - .init(anyString(), any(CardinalInitService.class)); - - ThreeDSecureRequest request = new ThreeDSecureRequest(); - try { - sut.initialize(context, configuration, request, cardinalInitializeCallback); - fail("should not get here"); - } catch (BraintreeException e) { - assertEquals("Cardinal SDK init Error.", e.getMessage()); - assertSame(runtimeException, e.getCause()); - } - } - - @Test - public void continueLookup_continuesCardinalLookup() throws BraintreeException { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureLookup threeDSecureLookup = mock(ThreeDSecureLookup.class); - when(threeDSecureLookup.getTransactionId()).thenReturn("sample-transaction-id"); - when(threeDSecureLookup.getPareq()).thenReturn("sample-payer-authentication-request"); - - ThreeDSecureResult threeDSecureResult = mock(ThreeDSecureResult.class); - when(threeDSecureResult.getLookup()).thenReturn(threeDSecureLookup); - - sut.continueLookup(activity, threeDSecureResult, cardinalValidateReceiver); - - verify(cardinalInstance).cca_continue( - "sample-transaction-id", - "sample-payer-authentication-request", - activity, - cardinalValidateReceiver - ); - } - - @Test - public void continueLookup_onCardinalRuntimeException_throwsError() { - when(Cardinal.getInstance()).thenReturn(cardinalInstance); - RuntimeException runtimeException = new RuntimeException("fake message"); - doThrow(runtimeException) - .when(cardinalInstance).cca_continue(anyString(), anyString(), any(Activity.class), any(CardinalValidateReceiver.class)); - CardinalClient sut = new CardinalClient(); - - ThreeDSecureLookup threeDSecureLookup = mock(ThreeDSecureLookup.class); - when(threeDSecureLookup.getTransactionId()).thenReturn("sample-transaction-id"); - when(threeDSecureLookup.getPareq()).thenReturn("sample-payer-authentication-request"); - - ThreeDSecureResult threeDSecureResult = mock(ThreeDSecureResult.class); - when(threeDSecureResult.getLookup()).thenReturn(threeDSecureLookup); - - try { - sut.continueLookup(activity, threeDSecureResult, cardinalValidateReceiver); - fail("should not get here"); - } catch (BraintreeException e) { - assertEquals("Cardinal SDK cca_continue Error.", e.getMessage()); - assertSame(runtimeException, e.getCause()); - } - } -} diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.kt b/ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.kt new file mode 100644 index 0000000000..0fb740f71e --- /dev/null +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/CardinalClientUnitTest.kt @@ -0,0 +1,270 @@ +package com.braintreepayments.api + +import android.content.Context +import androidx.fragment.app.FragmentActivity +import com.cardinalcommerce.cardinalmobilesdk.Cardinal +import com.cardinalcommerce.cardinalmobilesdk.enums.CardinalEnvironment +import com.cardinalcommerce.cardinalmobilesdk.enums.CardinalUiType +import com.cardinalcommerce.cardinalmobilesdk.models.CardinalConfigurationParameters +import com.cardinalcommerce.cardinalmobilesdk.services.CardinalInitService +import com.cardinalcommerce.cardinalmobilesdk.services.CardinalValidateReceiver +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.slot +import io.mockk.verify +import junit.framework.TestCase.assertEquals +import junit.framework.TestCase.assertSame +import junit.framework.TestCase.assertTrue +import junit.framework.TestCase.fail +import org.junit.Before +import org.junit.Test + + +class CardinalClientUnitTest { + + private lateinit var cardinalInstance: Cardinal + private lateinit var activity: FragmentActivity + private lateinit var configuration: Configuration + private lateinit var context: Context + private lateinit var cardinalInitializeCallback: CardinalInitializeCallback + private lateinit var cardinalValidateReceiver: CardinalValidateReceiver + + @Before + fun beforeEach() { + mockkStatic(Cardinal::class) + + context = mockk(relaxed = true) + configuration = mockk(relaxed = true) + cardinalInitializeCallback = mockk(relaxed = true) + cardinalInstance = mockk(relaxed = true) + activity = mockk(relaxed = true) + cardinalValidateReceiver = mockk(relaxed = true) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_configuresDefaultCardinalConfigurationParameters() { + every { Cardinal.getInstance() } returns cardinalInstance + + val sut = CardinalClient() + val request = ThreeDSecureRequest() + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val parametersSlot = slot() + verify { cardinalInstance.configure(context, capture(parametersSlot)) } + + val parameters = parametersSlot.captured + assertEquals(CardinalEnvironment.STAGING, parameters.environment) + assertEquals(8000, parameters.requestTimeout.toLong()) + assertTrue(parameters.isEnableDFSync) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_whenV2UiCustomizationNotNull_setsCardinalConfigurationParameters() { + every { Cardinal.getInstance() } returns cardinalInstance + + val sut = CardinalClient() + val v2UiCustomization = ThreeDSecureV2UiCustomization() + val request = ThreeDSecureRequest() + request.v2UiCustomization = v2UiCustomization + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val parametersSlot = slot() + verify { cardinalInstance.configure(context, capture(parametersSlot)) } + + val parameters = parametersSlot.captured + assertEquals( + request.v2UiCustomization!!.cardinalUiCustomization, + parameters.uiCustomization + ) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_whenEnvironmentProduction_configuresCardinalEnvironmentProduction() { + every { Cardinal.getInstance() } returns cardinalInstance + every { configuration.environment } returns "production" + + val sut = CardinalClient() + val request = ThreeDSecureRequest() + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val parametersSlot = slot() + verify { cardinalInstance.configure(context, capture(parametersSlot)) } + + val parameters = parametersSlot.captured + assertEquals(CardinalEnvironment.PRODUCTION, parameters.environment) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_whenUiTypeNotNull_setsCardinalConfigurationParameters() { + every { Cardinal.getInstance() } returns cardinalInstance + + val sut = CardinalClient() + val request = ThreeDSecureRequest().apply { + uiType = ThreeDSecureRequest.BOTH + } + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val parametersSlot = slot() + verify { cardinalInstance.configure(context, capture(parametersSlot)) } + + val parameters = parametersSlot.captured + assertEquals(CardinalUiType.BOTH, parameters.uiType) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_whenRenderTypeNotNull_setsCardinalConfigurationParameters() { + every { Cardinal.getInstance() } returns cardinalInstance + + val sut = CardinalClient() + val request = ThreeDSecureRequest().apply { + renderTypes = listOf( + ThreeDSecureRequest.OTP, + ThreeDSecureRequest.SINGLE_SELECT, + ThreeDSecureRequest.MULTI_SELECT, + ThreeDSecureRequest.OOB, + ThreeDSecureRequest.RENDER_HTML, + ) + } + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val parametersSlot = slot() + verify { cardinalInstance.configure(context, capture(parametersSlot)) } + + val parameters = parametersSlot.captured + assertEquals(5, parameters.renderType.length()) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_returnsConsumerSessionIdToListener() { + every { Cardinal.getInstance() } returns cardinalInstance + every { configuration.cardinalAuthenticationJwt } returns "token" + + val sut = CardinalClient() + val request = ThreeDSecureRequest() + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val cardinalInitServiceSlot = slot() + verify { cardinalInstance.init("token", capture(cardinalInitServiceSlot)) } + + val cardinalInitService = cardinalInitServiceSlot.captured + cardinalInitService.onSetupCompleted("session-id") + + verify { cardinalInitializeCallback.onResult(sut.consumerSessionId, null) } + assertEquals("session-id", sut.consumerSessionId) + } + + @Test + @Throws(BraintreeException::class) + fun initialize_whenConsumerSessionIdIsNull_returnsBraintreeExceptionToListener() { + every { Cardinal.getInstance() } returns cardinalInstance + every { configuration.cardinalAuthenticationJwt } returns "token" + + val sut = CardinalClient() + val request = ThreeDSecureRequest() + sut.initialize(context, configuration, request, cardinalInitializeCallback) + + val cardinalInitServiceSlot = slot() + verify { cardinalInstance.init("token", capture(cardinalInitServiceSlot)) } + + val cardinalInitService = cardinalInitServiceSlot.captured + cardinalInitService.onValidated(null, null) + + val exceptionSlot = slot() + verify { cardinalInitializeCallback.onResult(isNull(), capture(exceptionSlot)) } + assertEquals(exceptionSlot.captured.message, "consumer session id not available") + } + + @Test + fun initialize_onCardinalConfigureRuntimeException_throwsError() { + every { Cardinal.getInstance() } returns cardinalInstance + every { configuration.cardinalAuthenticationJwt } returns "token" + + val sut = CardinalClient() + val runtimeException = RuntimeException("fake message") + every { cardinalInstance.configure(any(), any()) } throws runtimeException + + val request = ThreeDSecureRequest() + try { + sut.initialize(context, configuration, request, cardinalInitializeCallback) + fail("should not get here") + } catch (e: BraintreeException) { + assertEquals("Cardinal SDK configure Error.", e.message) + assertSame(runtimeException, e.cause) + } + } + + @Test + fun initialize_onCardinalInitRuntimeException_throwsError() { + every { Cardinal.getInstance() } returns cardinalInstance + every { configuration.cardinalAuthenticationJwt } returns "token" + + val sut = CardinalClient() + val runtimeException = RuntimeException("fake message") + every { cardinalInstance.init(any(), any()) } throws runtimeException + + val request = ThreeDSecureRequest() + try { + sut.initialize(context, configuration, request, cardinalInitializeCallback) + fail("should not get here") + } catch (e: BraintreeException) { + assertEquals("Cardinal SDK init Error.", e.message) + assertSame(runtimeException, e.cause) + } + } + + @Test + @Throws(BraintreeException::class) + fun continueLookup_continuesCardinalLookup() { + every { Cardinal.getInstance() } returns cardinalInstance + + val sut = CardinalClient() + val threeDSecureLookup = mockk(relaxed = true) + + every { threeDSecureLookup.transactionId } returns "sample-transaction-id" + every { threeDSecureLookup.pareq } returns "sample-payer-authentication-request" + + val threeDSecureResult = mockk(relaxed = true) + every { threeDSecureResult.lookup } returns threeDSecureLookup + + sut.continueLookup(activity, threeDSecureResult, cardinalValidateReceiver) + verify { + cardinalInstance.cca_continue( + "sample-transaction-id", + "sample-payer-authentication-request", + activity, + cardinalValidateReceiver + ) + } + } + + @Test + fun continueLookup_onCardinalRuntimeException_throwsError() { + every { Cardinal.getInstance() } returns cardinalInstance + + val runtimeException = RuntimeException("fake message") + every { cardinalInstance.cca_continue(any(), any(), any(), any()) } throws runtimeException + + val sut = CardinalClient() + val threeDSecureLookup = mockk(relaxed = true) + every { threeDSecureLookup.transactionId } returns "sample-transaction-id" + every { threeDSecureLookup.pareq } returns "sample-payer-authentication-request" + + val threeDSecureResult = mockk(relaxed = true) + every { threeDSecureResult.lookup } returns threeDSecureLookup + + try { + sut.continueLookup(activity, threeDSecureResult, cardinalValidateReceiver) + fail("should not get here") + } catch (e: BraintreeException) { + assertEquals("Cardinal SDK cca_continue Error.", e.message) + assertSame(runtimeException, e.cause) + } + } +} \ No newline at end of file diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/MockCardinalClientBuilder.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/MockCardinalClientBuilder.java index eb7e891d1d..7e7cf882e1 100644 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/MockCardinalClientBuilder.java +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/MockCardinalClientBuilder.java @@ -1,16 +1,16 @@ package com.braintreepayments.api; -import android.content.Context; - -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.content.Context; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + public class MockCardinalClientBuilder { private Exception error; diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureAPIUnitTest.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureAPIUnitTest.java index 93d20479b6..c9d268ca06 100644 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureAPIUnitTest.java +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureAPIUnitTest.java @@ -5,10 +5,10 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -60,7 +60,7 @@ public void performLookup_onSuccess_callbackThreeDSecureResult() { ThreeDSecureResultCallback callback = mock(ThreeDSecureResultCallback.class); sut.performLookup(threeDSecureRequest, "another-session-id", callback); - verify(callback).onResult(any(ThreeDSecureResult.class), (Exception) isNull()); + verify(callback).onResult(any(ThreeDSecureResult.class), isNull()); } @Test @@ -76,7 +76,7 @@ public void performLookup_onInvalidJSONResponse_callbackJSONException() { ThreeDSecureResultCallback callback = mock(ThreeDSecureResultCallback.class); sut.performLookup(threeDSecureRequest, "cardinal-session-id", callback); - verify(callback).onResult((ThreeDSecureResult) isNull(), any(JSONException.class)); + verify(callback).onResult(isNull(), any(JSONException.class)); } @Test @@ -93,7 +93,7 @@ public void performLookup_onPOSTFailure_callbackHTTPError() { ThreeDSecureResultCallback callback = mock(ThreeDSecureResultCallback.class); sut.performLookup(threeDSecureRequest, "cardinal-session-id", callback); - verify(callback).onResult((ThreeDSecureResult) isNull(), same(httpError)); + verify(callback).onResult(isNull(), same(httpError)); } @Test diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureActivityUnitTest.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureActivityUnitTest.java index 35ffc7cd9e..df7509a4bb 100644 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureActivityUnitTest.java +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureActivityUnitTest.java @@ -1,25 +1,12 @@ package com.braintreepayments.api; -import android.content.Intent; -import android.os.Bundle; - -import com.cardinalcommerce.cardinalmobilesdk.models.CardinalActionCode; -import com.cardinalcommerce.cardinalmobilesdk.models.ValidateResponse; -import com.cardinalcommerce.cardinalmobilesdk.services.CardinalValidateReceiver; - -import org.json.JSONException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.robolectric.RobolectricTestRunner; - import static android.app.Activity.RESULT_OK; import static com.braintreepayments.api.ThreeDSecureActivity.RESULT_COULD_NOT_START_CARDINAL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -27,8 +14,21 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Intent; +import android.os.Bundle; + import androidx.fragment.app.FragmentActivity; +import com.cardinalcommerce.cardinalmobilesdk.models.CardinalActionCode; +import com.cardinalcommerce.cardinalmobilesdk.models.ValidateResponse; +import com.cardinalcommerce.cardinalmobilesdk.services.CardinalValidateReceiver; + +import org.json.JSONException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.robolectric.RobolectricTestRunner; + @RunWith(RobolectricTestRunner.class) public class ThreeDSecureActivityUnitTest { diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureClientUnitTest.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureClientUnitTest.java index 54e2945f64..9fba3f7b5c 100644 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureClientUnitTest.java +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureClientUnitTest.java @@ -6,10 +6,10 @@ import static junit.framework.TestCase.assertNull; import static junit.framework.TestCase.assertSame; import static org.junit.Assert.assertFalse; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -215,7 +215,7 @@ public void performVerification_withInvalidRequest_postsException() throws Brain sut.performVerification(activity, request, threeDSecureResultCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(Exception.class); - verify(threeDSecureResultCallback).onResult((ThreeDSecureResult) isNull(), captor.capture()); + verify(threeDSecureResultCallback).onResult(isNull(), captor.capture()); assertEquals("The ThreeDSecureRequest nonce and amount cannot be null", captor.getValue().getMessage()); } @@ -232,7 +232,7 @@ public void performVerification_whenV1_throwsAnError() throws BraintreeException sut.performVerification(activity, basicRequest, threeDSecureResultCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(BraintreeException.class); - verify(threeDSecureResultCallback).onResult((ThreeDSecureResult) isNull(), captor.capture()); + verify(threeDSecureResultCallback).onResult(isNull(), captor.capture()); BraintreeException error = captor.getValue(); String expectedMessage = diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureLifecycleObserverUnitTest.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureLifecycleObserverUnitTest.java index 0325c49646..63cb232cf4 100644 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureLifecycleObserverUnitTest.java +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureLifecycleObserverUnitTest.java @@ -3,10 +3,10 @@ import static android.os.Looper.getMainLooper; import static com.braintreepayments.api.BraintreeRequestCodes.PAYPAL; import static com.braintreepayments.api.BraintreeRequestCodes.THREE_D_SECURE; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; diff --git a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureV2UnitTest.java b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureV2UnitTest.java index 43fa5c998c..bb89d1e498 100644 --- a/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureV2UnitTest.java +++ b/ThreeDSecure/src/test/java/com/braintreepayments/api/ThreeDSecureV2UnitTest.java @@ -6,10 +6,10 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -94,7 +94,7 @@ public void prepareLookup_returnsValidLookupJSONString() throws JSONException, B sut.prepareLookup(activity, basicRequest, callback); ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - verify(callback).onResult(same(basicRequest), captor.capture(), (Exception) isNull()); + verify(callback).onResult(same(basicRequest), captor.capture(), isNull()); String clientData = captor.getValue(); JSONObject lookup = new JSONObject(clientData); diff --git a/UnionPay/build.gradle b/UnionPay/build.gradle index a2b230bbfa..5323985e0b 100644 --- a/UnionPay/build.gradle +++ b/UnionPay/build.gradle @@ -37,10 +37,7 @@ dependencies { implementation deps.annotation testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation project(':TestUtils') testImplementation deps.coreKtx diff --git a/UnionPay/src/test/java/com/braintreepayments/api/UnionPayClientUnitTest.java b/UnionPay/src/test/java/com/braintreepayments/api/UnionPayClientUnitTest.java index ab7560956f..83caef6e9e 100644 --- a/UnionPay/src/test/java/com/braintreepayments/api/UnionPayClientUnitTest.java +++ b/UnionPay/src/test/java/com/braintreepayments/api/UnionPayClientUnitTest.java @@ -1,5 +1,17 @@ package com.braintreepayments.api; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.net.Uri; import org.json.JSONException; @@ -10,18 +22,6 @@ import org.mockito.ArgumentCaptor; import org.robolectric.RobolectricTestRunner; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @RunWith(RobolectricTestRunner.class) public class UnionPayClientUnitTest { @@ -133,7 +133,7 @@ public void enroll_callsListenerWithUnionPayEnrollmentIdAdded() throws JSONExcep sut.enroll(unionPayCard, unionPayEnrollCallback); ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(UnionPayEnrollment.class); - verify(unionPayEnrollCallback).onResult(resultCaptor.capture(), (Exception) isNull()); + verify(unionPayEnrollCallback).onResult(resultCaptor.capture(), isNull()); UnionPayEnrollment result = resultCaptor.getValue(); assertEquals("some-enrollment-id", result.getId()); @@ -150,7 +150,7 @@ public void enroll_failsIfUnionPayIsDisabled() { sut.enroll(unionPayCard, unionPayEnrollCallback); ArgumentCaptor exceptionCaptor = ArgumentCaptor.forClass(Exception.class); - verify(unionPayEnrollCallback).onResult((UnionPayEnrollment) isNull(), exceptionCaptor.capture()); + verify(unionPayEnrollCallback).onResult(isNull(), exceptionCaptor.capture()); Exception exception = exceptionCaptor.getValue(); assertTrue(exception instanceof ConfigurationException); diff --git a/Venmo/build.gradle b/Venmo/build.gradle index 41e01be869..1095c68b10 100644 --- a/Venmo/build.gradle +++ b/Venmo/build.gradle @@ -41,10 +41,7 @@ dependencies { testImplementation deps.robolectric testImplementation deps.androidxTestCore testImplementation deps.junitTest - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockitoCore testImplementation deps.jsonAssert testImplementation project(':TestUtils') } diff --git a/Venmo/src/test/java/com/braintreepayments/api/MockVenmoApiBuilder.java b/Venmo/src/test/java/com/braintreepayments/api/MockVenmoApiBuilder.java index a140ffacef..54548f0ae5 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/MockVenmoApiBuilder.java +++ b/Venmo/src/test/java/com/braintreepayments/api/MockVenmoApiBuilder.java @@ -1,7 +1,7 @@ package com.braintreepayments.api; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; diff --git a/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java b/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java index b0c23b770a..6e6278993e 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java +++ b/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java @@ -13,12 +13,12 @@ import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertSame; import static junit.framework.TestCase.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.endsWith; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.endsWith; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -725,7 +725,7 @@ public void onActivityResult_onGraphQLPostSuccess_returnsNonceToCallback_andSend sut.onActivityResult(activity, AppCompatActivity.RESULT_OK, intent, onActivityResultCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(VenmoAccountNonce.class); - verify(onActivityResultCallback).onResult(captor.capture(), (Exception) isNull()); + verify(onActivityResultCallback).onResult(captor.capture(), isNull()); VenmoAccountNonce nonce = captor.getValue(); assertEquals("fake-venmo-nonce", nonce.getString()); diff --git a/Venmo/src/test/java/com/braintreepayments/api/VenmoLifecycleObserverUnitTest.java b/Venmo/src/test/java/com/braintreepayments/api/VenmoLifecycleObserverUnitTest.java index 7360595a58..2c5b021e1f 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/VenmoLifecycleObserverUnitTest.java +++ b/Venmo/src/test/java/com/braintreepayments/api/VenmoLifecycleObserverUnitTest.java @@ -1,9 +1,9 @@ package com.braintreepayments.api; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/VisaCheckout/build.gradle b/VisaCheckout/build.gradle index 0353f5c3aa..c86514bd78 100644 --- a/VisaCheckout/build.gradle +++ b/VisaCheckout/build.gradle @@ -46,10 +46,8 @@ dependencies { testImplementation deps.androidxTestRules testImplementation deps.androidxTestRunner testImplementation deps.robolectric - testImplementation deps.powermockJunit - testImplementation deps.powermockRule - testImplementation deps.powermockMockito - testImplementation deps.powermockClassloading + testImplementation deps.mockk + testImplementation deps.mockitoCore testImplementation deps.jsonAssert } diff --git a/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.java b/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.java deleted file mode 100644 index d81e6cccad..0000000000 --- a/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.braintreepayments.api; - -import com.visa.checkout.VisaPaymentSummary; - -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.rule.PowerMockRule; -import org.robolectric.RobolectricTestRunner; -import org.skyscreamer.jsonassert.JSONAssert; -import org.skyscreamer.jsonassert.JSONCompareMode; - -import static junit.framework.Assert.assertEquals; -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; - -@RunWith(RobolectricTestRunner.class) -@PowerMockIgnore({"org.powermock.*", "org.mockito.*", "org.robolectric.*", "android.*", "androidx.*"}) -@PrepareForTest({VisaPaymentSummary.class}) -public class VisaCheckoutAccountUnitTest { - - @Rule - public PowerMockRule powerMockRule = new PowerMockRule(); - - private VisaPaymentSummary visaPaymentSummary; - - @Before - public void beforeEach() { - visaPaymentSummary = mock(VisaPaymentSummary.class); - } - - @Test - public void build_withNullVisaPaymentSummary_buildsEmptyPaymentMethod() throws JSONException { - JSONObject expectedBase = new JSONObject() - .put("visaCheckoutCard", new JSONObject()) - .put("_meta", new JSONObject() - .put("source", "form") - .put("integration", "custom") - .put("sessionId", "1234") - .put("platform", "android") - ); - - VisaCheckoutAccount visaCheckoutAccount = new VisaCheckoutAccount(null); - visaCheckoutAccount.setSessionId("1234"); - JSONObject json = visaCheckoutAccount.buildJSON(); - - JSONAssert.assertEquals(expectedBase, json, JSONCompareMode.STRICT); - } - - @Test - public void build_withVisaPaymentSummary_buildsExpectedPaymentMethod() throws JSONException { - when(visaPaymentSummary.getCallId()).thenReturn("stubbedCallId"); - when(visaPaymentSummary.getEncKey()).thenReturn("stubbedEncKey"); - when(visaPaymentSummary.getEncPaymentData()).thenReturn("stubbedEncPaymentData"); - - VisaCheckoutAccount visaCheckoutAccount = new VisaCheckoutAccount(visaPaymentSummary); - visaCheckoutAccount.setSessionId("1234"); - JSONObject json = visaCheckoutAccount.buildJSON(); - - JSONObject expectedBase = new JSONObject(); - JSONObject expectedPaymentMethodNonce = new JSONObject(); - expectedPaymentMethodNonce.put("callId", "stubbedCallId"); - expectedPaymentMethodNonce.put("encryptedKey", "stubbedEncKey"); - expectedPaymentMethodNonce.put("encryptedPaymentData", "stubbedEncPaymentData"); - expectedBase.put("visaCheckoutCard", expectedPaymentMethodNonce); - - expectedBase.put("_meta", new JSONObject() - .put("source", "form") - .put("integration", "custom") - .put("sessionId", "1234") - .put("platform", "android") - ); - - JSONAssert.assertEquals(expectedBase, json, JSONCompareMode.STRICT); - } - - @Test - public void getApiPath_returnsCorrectApiPath() { - assertEquals("visa_checkout_cards", new VisaCheckoutAccount(null).getApiPath()); - } -} diff --git a/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.kt b/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.kt new file mode 100644 index 0000000000..3f0a28ea1c --- /dev/null +++ b/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutAccountUnitTest.kt @@ -0,0 +1,73 @@ +package com.braintreepayments.api + +import com.visa.checkout.VisaPaymentSummary +import io.mockk.every +import io.mockk.mockk +import junit.framework.TestCase.assertEquals +import org.json.JSONException +import org.json.JSONObject +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.skyscreamer.jsonassert.JSONAssert +import org.skyscreamer.jsonassert.JSONCompareMode + +@RunWith(RobolectricTestRunner::class) +class VisaCheckoutAccountUnitTest { + + private lateinit var visaPaymentSummary: VisaPaymentSummary + + @Before + fun beforeEach() { + visaPaymentSummary = mockk(relaxed = true) + } + + @Test + @Throws(JSONException::class) + fun build_withNullVisaPaymentSummary_buildsEmptyPaymentMethod() { + val expectedBase = JSONObject() + .put("visaCheckoutCard", JSONObject()) + .put( + "_meta", JSONObject() + .put("source", "form") + .put("integration", "custom") + .put("sessionId", "1234") + .put("platform", "android") + ) + val visaCheckoutAccount = VisaCheckoutAccount(null) + visaCheckoutAccount.setSessionId("1234") + val json = visaCheckoutAccount.buildJSON() + JSONAssert.assertEquals(expectedBase, json, JSONCompareMode.STRICT) + } + + @Test + @Throws(JSONException::class) + fun build_withVisaPaymentSummary_buildsExpectedPaymentMethod() { + every { visaPaymentSummary.callId } returns "stubbedCallId" + every { visaPaymentSummary.encKey } returns "stubbedEncKey" + every { visaPaymentSummary.encPaymentData } returns "stubbedEncPaymentData" + val visaCheckoutAccount = VisaCheckoutAccount(visaPaymentSummary) + visaCheckoutAccount.setSessionId("1234") + val json = visaCheckoutAccount.buildJSON() + val expectedBase = JSONObject() + val expectedPaymentMethodNonce = JSONObject() + expectedPaymentMethodNonce.put("callId", "stubbedCallId") + expectedPaymentMethodNonce.put("encryptedKey", "stubbedEncKey") + expectedPaymentMethodNonce.put("encryptedPaymentData", "stubbedEncPaymentData") + expectedBase.put("visaCheckoutCard", expectedPaymentMethodNonce) + expectedBase.put( + "_meta", JSONObject() + .put("source", "form") + .put("integration", "custom") + .put("sessionId", "1234") + .put("platform", "android") + ) + JSONAssert.assertEquals(expectedBase, json, JSONCompareMode.STRICT) + } + + @Test + fun apiPath_returnsCorrectApiPath() { + assertEquals("visa_checkout_cards", VisaCheckoutAccount(null).apiPath) + } +} \ No newline at end of file diff --git a/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.java b/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.java deleted file mode 100644 index 5b3e278e9a..0000000000 --- a/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.braintreepayments.api; - -import com.visa.checkout.Profile; -import com.visa.checkout.Profile.CardBrand; -import com.visa.checkout.Profile.ProfileBuilder; -import com.visa.checkout.VisaCheckoutSdk; -import com.visa.checkout.VisaPaymentSummary; - -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.rule.PowerMockRule; -import org.robolectric.RobolectricTestRunner; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.when; - -@RunWith(RobolectricTestRunner.class) -@PowerMockIgnore({"org.powermock.*", "org.mockito.*", "org.robolectric.*", "android.*", "androidx.*", "com.visa.checkout.Profile", "com.visa.checkout.Profile.ProfileBuilder"}) -@PrepareForTest({ VisaPaymentSummary.class, VisaCheckoutSdk.class }) -// TODO: Investigate Robolectric / PowerMock Combination test failures -@Ignore("These tests are failing because of VisaCheckout classes marked 'final'. Using Braintree wrapped types for Visa lib may help here in the future.") -public class VisaCheckoutClientUnitTest { - - @Rule - public PowerMockRule powerMockRule = new PowerMockRule(); - - private Configuration configurationWithVisaCheckout; - private VisaPaymentSummary visaPaymentSummary; - - @Before - public void setup() throws Exception { - configurationWithVisaCheckout = Configuration.fromJson(Fixtures.CONFIGURATION_WITH_VISA_CHECKOUT); - - visaPaymentSummary = PowerMockito.mock(VisaPaymentSummary.class); - when(visaPaymentSummary.getCallId()).thenReturn("stubbedCallId"); - when(visaPaymentSummary.getEncKey()).thenReturn("stubbedEncKey"); - when(visaPaymentSummary.getEncPaymentData()).thenReturn("stubbedEncPaymentData"); - PowerMockito.whenNew(VisaPaymentSummary.class).withAnyArguments().thenReturn(visaPaymentSummary); - } - - @Test - public void createProfileBuilder_whenNotEnabled_throwsConfigurationException() { - ApiClient apiClient = new MockApiClientBuilder().build(); - - Configuration configuration = TestConfigurationBuilder.basicConfig(); - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(configuration) - .build(); - - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - VisaCheckoutCreateProfileBuilderCallback listener = mock(VisaCheckoutCreateProfileBuilderCallback.class); - sut.createProfileBuilder(listener); - - ArgumentCaptor captor = ArgumentCaptor.forClass(ConfigurationException.class); - verify(listener, times(1)).onResult((ProfileBuilder) isNull(), captor.capture()); - - ConfigurationException configurationException = captor.getValue(); - assertEquals("Visa Checkout is not enabled.", configurationException.getMessage()); - } - - @Test - public void createProfileBuilder_whenProduction_usesProductionConfig() throws Exception { - final CountDownLatch lock = new CountDownLatch(1); - - ApiClient apiClient = new MockApiClientBuilder().build(); - String configString = new TestConfigurationBuilder() - .environment("production") - .visaCheckout(new TestConfigurationBuilder.TestVisaCheckoutConfigurationBuilder() - .apikey("gwApiKey") - .supportedCardTypes(CardBrand.VISA, CardBrand.MASTERCARD) - .externalClientId("gwExternalClientId")) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(Configuration.fromJson(configString)) - .build(); - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - sut.createProfileBuilder(new VisaCheckoutCreateProfileBuilderCallback() { - @Override - public void onResult(ProfileBuilder profileBuilder, Exception error) { - List expectedCardBrands = Arrays.asList(CardBrand.VISA, CardBrand.MASTERCARD); - Profile profile = profileBuilder.build(); - assertNotNull(profile); - lock.countDown(); - } - }); - - lock.await(); - } - - @Test - public void createProfileBuilder_whenNotProduction_usesSandboxConfig() throws Exception { - final CountDownLatch lock = new CountDownLatch(1); - - ApiClient apiClient = new MockApiClientBuilder().build(); - String configString = new TestConfigurationBuilder() - .environment("environment") - .visaCheckout(new TestConfigurationBuilder.TestVisaCheckoutConfigurationBuilder() - .apikey("gwApiKey") - .supportedCardTypes(CardBrand.VISA, CardBrand.MASTERCARD) - .externalClientId("gwExternalClientId")) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(Configuration.fromJson(configString)) - .build(); - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - sut.createProfileBuilder(new VisaCheckoutCreateProfileBuilderCallback() { - @Override - public void onResult(ProfileBuilder profileBuilder, Exception error) { - List expectedCardBrands = Arrays.asList(CardBrand.VISA, CardBrand.MASTERCARD); - Profile profile = profileBuilder.build(); - assertNotNull(profile); - lock.countDown(); - } - }); - - lock.await(); - } - - @Test - public void tokenize_whenSuccessful_postsVisaPaymentMethodNonce() throws JSONException { - ApiClient apiClient = new MockApiClientBuilder() - .tokenizeRESTSuccess(new JSONObject(Fixtures.PAYMENT_METHODS_VISA_CHECKOUT_RESPONSE)) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(configurationWithVisaCheckout) - .build(); - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - VisaCheckoutTokenizeCallback listener = mock(VisaCheckoutTokenizeCallback.class); - sut.tokenize(visaPaymentSummary, listener); - - verify(listener).onResult(any(VisaCheckoutNonce.class), (Exception) isNull()); - } - - @Test - public void tokenize_whenSuccessful_sendsAnalyticEvent() throws JSONException { - ApiClient apiClient = new MockApiClientBuilder() - .tokenizeRESTSuccess(new JSONObject(Fixtures.PAYMENT_METHODS_VISA_CHECKOUT_RESPONSE)) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(configurationWithVisaCheckout) - .build(); - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - VisaCheckoutTokenizeCallback listener = mock(VisaCheckoutTokenizeCallback.class); - sut.tokenize(visaPaymentSummary, listener); - - verify(braintreeClient).sendAnalyticsEvent("visacheckout.tokenize.succeeded"); - } - - @Test - public void tokenize_whenFailure_postsException() { - Exception tokenizeError = new Exception("Mock Failure"); - ApiClient apiClient = new MockApiClientBuilder() - .tokenizeRESTError(tokenizeError) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(configurationWithVisaCheckout) - .build(); - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - VisaCheckoutTokenizeCallback listener = mock(VisaCheckoutTokenizeCallback.class); - sut.tokenize(visaPaymentSummary, listener); - - verify(listener).onResult(null, tokenizeError); - } - - @Test - public void tokenize_whenFailure_sendsAnalyticEvent() { - Exception tokenizeError = new Exception("Mock Failure"); - ApiClient apiClient = new MockApiClientBuilder() - .tokenizeRESTError(tokenizeError) - .build(); - - BraintreeClient braintreeClient = new MockBraintreeClientBuilder() - .configuration(configurationWithVisaCheckout) - .build(); - VisaCheckoutClient sut = new VisaCheckoutClient(braintreeClient, apiClient); - - VisaCheckoutTokenizeCallback listener = mock(VisaCheckoutTokenizeCallback.class); - sut.tokenize(visaPaymentSummary, listener); - - verify(braintreeClient).sendAnalyticsEvent("visacheckout.tokenize.failed"); - } -} diff --git a/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.kt b/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.kt new file mode 100644 index 0000000000..d0c73d71af --- /dev/null +++ b/VisaCheckout/src/test/java/com/braintreepayments/api/VisaCheckoutClientUnitTest.kt @@ -0,0 +1,170 @@ +package com.braintreepayments.api + +import com.braintreepayments.api.Configuration.Companion.fromJson +import com.braintreepayments.api.TestConfigurationBuilder.TestVisaCheckoutConfigurationBuilder +import com.visa.checkout.Profile.CardBrand +import com.visa.checkout.VisaPaymentSummary +import io.mockk.every +import io.mockk.mockk +import io.mockk.slot +import io.mockk.verify +import junit.framework.TestCase.assertEquals +import junit.framework.TestCase.assertNotNull +import org.json.JSONException +import org.json.JSONObject +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.util.Arrays +import java.util.concurrent.CountDownLatch + +@RunWith(RobolectricTestRunner::class) +class VisaCheckoutClientUnitTest { + + private lateinit var configurationWithVisaCheckout: Configuration + private lateinit var visaPaymentSummary: VisaPaymentSummary + + @Before + @Throws(Exception::class) + fun setup() { + configurationWithVisaCheckout = fromJson(Fixtures.CONFIGURATION_WITH_VISA_CHECKOUT) + visaPaymentSummary = mockk(relaxed = true) + + every { visaPaymentSummary.callId } returns "stubbedCallId" + every { visaPaymentSummary.encKey } returns "stubbedEncKey" + every { visaPaymentSummary.encPaymentData } returns "stubbedEncPaymentData" + } + + @Test + fun createProfileBuilder_whenNotEnabled_throwsConfigurationException() { + val apiClient = MockkApiClientBuilder().build() + val configuration = TestConfigurationBuilder.basicConfig() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(configuration) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + val listener = mockk(relaxed = true) + sut.createProfileBuilder(listener) + + val configurationExceptionSlot = slot() + verify(exactly = 1) { listener.onResult(null, capture(configurationExceptionSlot)) } + + val configurationException = configurationExceptionSlot.captured + assertEquals("Visa Checkout is not enabled.", configurationException.message) + } + + @Test + @Throws(Exception::class) + fun createProfileBuilder_whenProduction_usesProductionConfig() { + val lock = CountDownLatch(1) + val apiClient = MockkApiClientBuilder().build() + val configString = TestConfigurationBuilder() + .environment("production") + .visaCheckout( + TestVisaCheckoutConfigurationBuilder() + .apikey("gwApiKey") + .supportedCardTypes(CardBrand.VISA, CardBrand.MASTERCARD) + .externalClientId("gwExternalClientId") + ) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(fromJson(configString)) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + sut.createProfileBuilder { profileBuilder, error -> + val expectedCardBrands = Arrays.asList(CardBrand.VISA, CardBrand.MASTERCARD) + val profile = profileBuilder!!.build() + assertNotNull(profile) + lock.countDown() + } + lock.await() + } + + @Test + @Throws(Exception::class) + fun createProfileBuilder_whenNotProduction_usesSandboxConfig() { + val lock = CountDownLatch(1) + val apiClient = MockkApiClientBuilder().build() + val configString = TestConfigurationBuilder() + .environment("environment") + .visaCheckout( + TestVisaCheckoutConfigurationBuilder() + .apikey("gwApiKey") + .supportedCardTypes(CardBrand.VISA, CardBrand.MASTERCARD) + .externalClientId("gwExternalClientId") + ) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(fromJson(configString)) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + sut.createProfileBuilder { profileBuilder, error -> + val expectedCardBrands = Arrays.asList(CardBrand.VISA, CardBrand.MASTERCARD) + val profile = profileBuilder!!.build() + assertNotNull(profile) + lock.countDown() + } + lock.await() + } + + @Test + @Throws(JSONException::class) + fun tokenize_whenSuccessful_postsVisaPaymentMethodNonce() { + val apiClient = MockkApiClientBuilder() + .tokenizeRESTSuccess(JSONObject(Fixtures.PAYMENT_METHODS_VISA_CHECKOUT_RESPONSE)) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(configurationWithVisaCheckout) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + val listener = mockk(relaxed = true) + sut.tokenize(visaPaymentSummary, listener) + verify { listener.onResult(any(), null) } + } + + @Test + @Throws(JSONException::class) + fun tokenize_whenSuccessful_sendsAnalyticEvent() { + val apiClient = MockkApiClientBuilder() + .tokenizeRESTSuccess(JSONObject(Fixtures.PAYMENT_METHODS_VISA_CHECKOUT_RESPONSE)) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(configurationWithVisaCheckout) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + val listener = mockk(relaxed = true) + sut.tokenize(visaPaymentSummary, listener) + verify { braintreeClient.sendAnalyticsEvent("visacheckout.tokenize.succeeded") } + } + + @Test + fun tokenize_whenFailure_postsException() { + val tokenizeError = Exception("Mock Failure") + val apiClient = MockkApiClientBuilder() + .tokenizeRESTError(tokenizeError) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(configurationWithVisaCheckout) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + val listener = mockk(relaxed = true) + sut.tokenize(visaPaymentSummary, listener) + verify { listener.onResult(null, tokenizeError) } + } + + @Test + fun tokenize_whenFailure_sendsAnalyticEvent() { + val tokenizeError = Exception("Mock Failure") + val apiClient = MockkApiClientBuilder() + .tokenizeRESTError(tokenizeError) + .build() + val braintreeClient = MockkBraintreeClientBuilder() + .configurationSuccess(configurationWithVisaCheckout) + .build() + val sut = VisaCheckoutClient(braintreeClient, apiClient) + val listener = mockk(relaxed = true) + sut.tokenize(visaPaymentSummary, listener) + verify { braintreeClient.sendAnalyticsEvent("visacheckout.tokenize.failed") } + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index b66342c599..422afac8b4 100644 --- a/build.gradle +++ b/build.gradle @@ -23,8 +23,6 @@ buildscript { ext.versions = [ "kotlin" : "1.7.0", "androidxTest" : "1.4.0", - "powermock" : '2.0.9', - "powermockLegacy": "1.7.4", // NEXT MAJOR VERSION: Use a single up-to-date room version once we remove Java 7 support in favor of Java 11 "room" : roomVersion, "playServices" : "19.1.0", @@ -66,20 +64,9 @@ buildscript { "junitTest" : "androidx.test.ext:junit:1.1.3", "robolectric" : "org.robolectric:robolectric:4.7.3", "dexmakerMockito" : "com.google.dexmaker:dexmaker-mockito:1.2", - "mockitoCore" : "org.mockito:mockito-core:3.6.0", + "mockitoCore" : "org.mockito:mockito-core:5.3.1", "jsonAssert" : "org.skyscreamer:jsonassert:1.5.1", "mockk" : "io.mockk:mockk:1.13.4", - - "powermockJunit" : "org.powermock:powermock-module-junit4:${versions.powermock}", - "powermockRule" : "org.powermock:powermock-module-junit4-rule:${versions.powermock}", - "powermockMockito" : "org.powermock:powermock-api-mockito2:${versions.powermock}", - "powermockClassloading" : "org.powermock:powermock-classloading-xstream:${versions.powermock}", - - // Legacy versions of the powermock libraries are required until 3DS and Visa Checkout tests can be updated to resolve robolectric/powermock test issues - "powermockJunitLegacy" : "org.powermock:powermock-module-junit4:${versions.powermockLegacy}", - "powermockRuleLegacy" : "org.powermock:powermock-module-junit4-rule:${versions.powermockLegacy}", - "powermockMockitoLegacy" : "org.powermock:powermock-api-mockito:${versions.powermockLegacy}", - "powermockClassloadingLegacy": "org.powermock:powermock-classloading-xstream:${versions.powermockLegacy}", ] dependencies {