# Unit testing the quickstart flow This is a complete test of the [quickstart](/docs/developer/sdk/getting-started/quickstart)'s authorize → capture flow: it mocks `RatepayClient`, stubs an `Accepted` outcome for both calls, and asserts the code under test reacts correctly, with no network access, so no sandbox credentials required. The examples use JUnit 5 plus Mockito (Java) or MockK (Kotlin), neither ships with the SDK. Add them as test dependencies. Assume the code under test is a small method that wraps the quickstart flow: ```java Java — code under test public class CheckoutService { private final RatepayClient client; public CheckoutService(RatepayClient client) { this.client = client; } public String authorizeAndCapture(AuthorizationRequest request, CaptureRequest captureRequest) { AuthorizeOutcome outcome = client.authorize(request, null); if (outcome.kind() != AuthorizeOutcome.Kind.ACCEPTED) { throw new IllegalStateException("Authorization not accepted: " + outcome.kind()); } CaptureOutcome captureOutcome = client.capture(outcome.ratepayTransactionId(), captureRequest, null); if (captureOutcome.kind() != CaptureOutcome.Kind.ACCEPTED) { throw new IllegalStateException("Capture not accepted: " + captureOutcome.kind()); } return ((CaptureOutcome.Accepted) captureOutcome).getRatepayCaptureId(); } } ``` ```kotlin Kotlin — code under test class CheckoutService(private val client: RatepayClient) { fun authorizeAndCapture(request: AuthorizationRequest, captureRequest: CaptureRequest): String { val outcome = client.authorize(request) check(outcome is AuthorizeOutcome.Accepted) { "Authorization not accepted: ${outcome.kind()}" } val captureOutcome = client.capture(outcome.ratepayTransactionId(), captureRequest) check(captureOutcome is CaptureOutcome.Accepted) { "Capture not accepted: ${captureOutcome.kind()}" } return captureOutcome.ratepayCaptureId } } ``` ## The test ```java Java (JUnit 5 + Mockito) import com.ratepay.sdk.AuthorizeOutcome; import com.ratepay.sdk.CaptureOutcome; import com.ratepay.sdk.RatepayClient; import com.ratepay.sdk.model.api.payment.*; import com.ratepay.sdk.model.extension.ResponseLinks; import org.junit.jupiter.api.Test; import java.math.BigDecimal; import java.time.OffsetDateTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class CheckoutServiceTest { @Test void authorizesThenCapturesOnAcceptance() { RatepayClient client = mock(RatepayClient.class); AuthorizeOutcome.Accepted authorizeAccepted = new AuthorizeOutcome.Accepted( "txn_123", null, OffsetDateTime.now(), null, new ResponseLinks(null), null ); when(client.authorize(any(), any())).thenReturn(authorizeAccepted); CaptureOutcome.Accepted captureAccepted = new CaptureOutcome.Accepted( "cap_456", OffsetDateTime.now(), new ResponseLinks(null) ); when(client.capture(eq("txn_123"), any(), any())).thenReturn(captureAccepted); CheckoutService service = new CheckoutService(client); String captureId = service.authorizeAndCapture(minimalAuthorizationRequest(), minimalCaptureRequest()); assertEquals("cap_456", captureId); } private static AuthorizationRequest minimalAuthorizationRequest() { return new AuthorizationRequest( new Buyer( new Address("Berlin", "DE", "Torstraße", "10119", null, "1"), new Contact("jane.doe@example.com", "+49 30 1234567"), null, null, new Person(java.time.LocalDate.of(1990, 4, 12), "Jane", "Doe", null), null ), "EUR", new PaymentMethod(PaymentOption.OPEN_INVOICE, TransferType.BANK_TRANSFER), java.util.List.of(new ShopBasket( new BigDecimal("29.99"), java.util.List.of(new Item( new BigDecimal("29.99"), "Wireless Mouse", BigDecimal.ONE, new BigDecimal("19"), "SKU-1001", null, null, null, null, null, null, null, null )), "SHOP-001", null, null, null, null )), null, null, null, null, null, null, null, null, null ); } private static CaptureRequest minimalCaptureRequest() { return new CaptureRequest(new BigDecimal("29.99"), null, null, null, null, null, null, null, null); } } ``` ```kotlin Kotlin (JUnit 5 + MockK) import com.ratepay.sdk.AuthorizeOutcome import com.ratepay.sdk.CaptureOutcome import com.ratepay.sdk.RatepayClient import com.ratepay.sdk.model.api.payment.* import io.mockk.every import io.mockk.mockk import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import java.math.BigDecimal import java.time.LocalDate class CheckoutServiceTest { @Test fun `authorizes then captures on acceptance`() { val client = mockk() val authorizeAccepted = mockk { every { ratepayTransactionId() } returns "txn_123" } every { client.authorize(any(), idempotencyKey = isNull()) } returns authorizeAccepted // named arg: authorize has a second overload taking an attestation token val captureAccepted = mockk { every { ratepayCaptureId } returns "cap_456" } every { client.capture("txn_123", any(), any()) } returns captureAccepted val service = CheckoutService(client) val captureId = service.authorizeAndCapture(minimalAuthorizationRequest(), minimalCaptureRequest()) assertEquals("cap_456", captureId) } private fun minimalAuthorizationRequest() = AuthorizationRequest( paymentMethod = PaymentMethod(PaymentOption.OPEN_INVOICE, TransferType.BANK_TRANSFER), currency = "EUR", buyer = Buyer( billingAddress = Address(street = "Torstraße", streetNumber = "1", zipCode = "10119", city = "Berlin", countryCode = "DE"), contact = Contact(email = "jane.doe@example.com", phone = "+49 30 1234567"), person = Person(firstName = "Jane", lastName = "Doe", dateOfBirth = LocalDate.of(1990, 4, 12)), ), shopBaskets = listOf(ShopBasket( partnerShopId = "SHOP-001", grossAmount = BigDecimal("29.99"), items = listOf(Item( grossUnitPrice = BigDecimal("29.99"), name = "Wireless Mouse", taxRate = BigDecimal("19"), quantity = BigDecimal.ONE, articleNumber = "SKU-1001", )), vats = null, )), ) private fun minimalCaptureRequest() = CaptureRequest(grossAmount = BigDecimal("29.99")) } ``` Two mocking details worth noticing: - The Java test constructs real `AuthorizeOutcome.Accepted` / `CaptureOutcome.Accepted` instances with `new`. The Kotlin test instead mocks the outcome types themselves with `mockk<...> { every { ... } }` and stubs only the properties `CheckoutService` actually reads. - `AuthorizeOutcome.ratepayTransactionId()` is a method, not a property, hence `every { ratepayTransactionId() } returns "txn_123"` in MockK, not `every { outcome.ratepayTransactionId }`.