How do you test a Stripe agent before production?
Start with Stripe test mode and test cards for the basics, then test the parts agents get wrong: refunds larger than the charge, duplicate charges on retries, webhook ordering, and idempotency keys. Those cases pass against mocks and fail against real Stripe.
Start with the official test environment
Stripe ships a genuinely good test mode with test cards and a full API that behaves like live mode. Use it. The Stripe test mode and test cards docs cover creating customers, charges, and subscriptions without moving real money.
Where agents actually break
The happy path is the easy part. An agent that can do the simple version of the task will still fall over on the cases below, and these are the ones worth building tests around:
- A refund larger than the original charge, which Stripe rejects but a mock approves
- A retry that fires a second charge because the agent did not send an idempotency key
- Webhooks that arrive out of order, so a
charge.succeededlands after acharge.refunded - A card decline or dispute mid-flow, where the agent should stop rather than continue
- Rate limits during a burst of charges, which change the timing the agent depends on
How to test it properly
Give the agent a realistic starting state, let it run the full task end to end, then check the state it left behind rather than the response it returned. Run the same scenario twice to confirm it does not duplicate work or corrupt state on a retry. Then deliberately inject a failure partway through, a rejected write or a rate limit, and confirm the agent recovers instead of charging ahead as if nothing happened.
Testing without building the environment yourself
You have a few options for the environment, and they trade off realism against setup. Stripe's own test mode (Stripe test mode and test cards) with the Stripe CLI for forwarding webhooks is the right starting point and covers most single-service cases. An HTTP mocking library like Mock Service Worker works when you only need canned responses to exercise your own error handling. Neither does the stateful, multi-service part well, where the refund has to be visible to the order record and a duplicate webhook has to be deduplicated across systems. That stateful, multi-service case is what Arga Labs is built to handle. It runs a Stripe twin alongside the other services the agent touches, so you point the agent's Stripe client at it, seed a customer and a charge, run the workflow end to end, and check the resulting state. Because it will replay a webhook or accept a repeated request under the same idempotency key on command, it reproduces the duplicate-charge and out-of-order cases a mock never surfaces.
Testing the duplicate-charge case
The bug that hurts most is a retry that charges twice. In Stripe test mode, drive the agent, then assert the customer was charged once. Passing the same idempotency key twice must return the same charge, not a new one:
pythonimport stripe # stripe.api_key is a test-mode key (sk_test_...)
def test_retry_does_not_double_charge():
customer = stripe.Customer.create(email="maria@example.com")
# simulate the agent retrying the same request (same idempotency key)
key = "order-1234-charge"
first = agent_charge(customer.id, 4200, idempotency_key=key)
retry = agent_charge(customer.id, 4200, idempotency_key=key)
assert first.id == retry.id # same charge returned, not a new one
charges = stripe.Charge.list(customer=customer.id)
assert len(charges.data) == 1 # exactly one charge exists
Without the idempotency key this test fails against real Stripe and silently passes against a naive mock, which is why the mock hides the bug.