neilberkman

neilberkman

We just published PaperTiger, a mock Stripe server we built to solve real pain points in our test suite.

The Problem

Testing Stripe integrations in Elixir (and in any language, really!) has some rough edges:

  • Stripe’s official stripe-mock is stateless - you can’t create a customer and then fetch it, which makes testing realistic flows impossible

  • Stripe’s webhook sandbox is limited - 5 endpoints max, dashboard-only management, no programmatic control

  • Shared test mode causes collisions - CI runs interfere with manual testing, leading to flaky tests

  • No time control - testing subscription renewals means waiting or hacking around Stripe’s billing cycle

We needed something that actually behaves like Stripe - stateful resources, proper webhook chains, and time control for billing cycles.

What PaperTiger Does

  • Stateful API - Create a customer, attach a payment method, subscribe them, and it all persists (in ETS)

  • Automatic webhook delivery - Resource changes emit properly-signed webhooks with retry logic

  • Time control - Accelerate time for subscription testing, or use manual mode for precise control

  • BillingEngine - Simulates subscription lifecycle: period rollovers, invoice creation, payment processing

  • Chaos mode - Inject payment failures with configurable decline codes for testing error paths

  • Contract testing - Run the same tests against PaperTiger and real Stripe to verify behavior matches

Quick Example

setup do
  {:ok, config: PaperTiger.stripity_stripe_config()}
end

test "subscription billing cycle", %{config: config} do
  {:ok, customer} = Stripe.Customer.create(%{email: "test@example.com"}, config)
  {:ok, sub} = Stripe.Subscription.create(%{customer: customer.id, ...}, config)
  
  assert sub.status == "active"
  
  # Advance time past the billing period
  PaperTiger.Clock.advance_days(32)
  
  # Subscription renewed, invoice created and paid
  {:ok, invoices} = Stripe.Invoice.list(%{customer: customer.id}, config)
  assert length(invoices.data) == 2
end

Links

https://github.com/EnaiaInc/paper_tiger

We’d welcome feedback, issues, or contributions. If you’ve dealt with similar Stripe testing headaches, hopefully this helps.

Showing Posts 1 to 2

neilberkman

neilberkman OP

PaperTiger is now v1.0.0 and is much more usable than the early versions. For us internally, this has been a major win: we replaced a large amount of custom Stripe mocking code with PaperTiger-based tests, and it’s also been very useful in development mode. If you used it early on and had any difficulties you may want to try again as it should be significantly improved. Details in the changelog.

neilberkman

neilberkman OP

PaperTiger is now v1.2.1, and it has gotten a lot more useful for real billing-test suites since the 1.0.0 announcement.

PaperTiger is a stateful local Stripe mock for Elixir apps. It now covers enough of Stripe’s billing surface that you can test much more of your app without hitting Stripe test mode.

More real billing flows work locally

  • PaymentIntent confirm/cancel/capture, including Charges and BalanceTransactions.
  • SetupIntent confirm/cancel flows, Checkout Session updates/line items, and invoice send/mark-uncollectible/attach-payment flows.
  • Payment Links, Billing Portal sessions/configurations, Promotion Codes, Credit Notes, Customer Balance, and basic Connect platform flows.

The mock is stricter, and models Stripe more faithfully

  • Stripe-style search endpoints and much better list filtering.
  • More realistic SubscriptionSchedule behavior.
  • Idempotency keys now reject same-key/different-payload requests like Stripe does.

Testing hooks are nicer now

  • Pluggable webhook delivery, for apps that want to own durable webhook delivery/retry.
  • Signed webhook request helpers, so you can test the same verification code you use in production.
  • Request spy helpers, so tests can assert exactly what your app sent to PaperTiger.

Full changelog: Changelog — PaperTiger v1.2.1
Hex package: paper_tiger | Hex

— All posts loaded —

Where Next? Top

Trending in Announcing Top

type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
ahamez
Hi everyone, I’ve been working on this protobuf library for 3 years. We use it in the company I work for, EasyMile, to communicate with ...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
kip
I’ll shortly be launching Text, a nascent text analysis library. Current functionality In this early version (not ready for prime time) ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews