neilberkman

neilberkman

PaperTiger - a stateful mock Stripe server for Elixir testing

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.

First 2 of 2 Posts! Switch mode

neilberkman

neilberkman

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

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

Where Next?

Trending in Announcing Top

bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
385 14863 120
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
shahryarjb
The Chelekom project is a library of Phoenix and LiveView components generated via Mix tasks to fit developer needs seamlessly. One of i...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
zachdaniel
Introducing AshStorage! Attachment and file management that slots directly into your resources :smiling_face_with_sunglasses: I had hope...
New

Other Trending Topics Top

type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
bjorng
We want to introduce a new native datatype to Erlang: native records. Although replacing all tuple records with native records is not our...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
yureehuh
Introduction Founded in 2017 by landscape ecologist and fire mitigation expert Harry Statter, Frontline developed the first fully integra...
New

We're in Beta

About us Mission Statement