Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a testing package #124

Closed
joshsmith opened this issue Nov 13, 2016 · 2 comments
Closed

Create a testing package #124

joshsmith opened this issue Nov 13, 2016 · 2 comments

Comments

@joshsmith
Copy link
Contributor

We should create a test "mock" system distributed as a separate package. This way, people can do the following:

[
  {:stripity_stripe, "~> 2.0"},
  {:stripity_stripe_testing, "~> 2.0", only: :test} 
]

The test package can distribute a lightweight replica of the Stripe service. That way, testing can be done something like the following:

test "retrieves all plans where the storage limit is greater than 30" do
  Stripe.Test.create(:plan, 10)
  Stripe.Test.create(:plan, 10, metadata: [storage_limit: 10])
  Stripe.Test.create(:plan, 10, metadata: [storage_limit: 35])
  Stripe.Test.create(:plan, 10, metadata: [storage_limit: 30])

  # This is business logic that will call the StripityStripe module
  plans = MyApp.Module.get_plans(:gt, 30) 

  assert Enum.count(plans) == 10
end

The data can be stored on a per-test basis in ETS, allowing users to build up the necessary state and tear it down without needing to know the intricacies of the system.

For example:

defmodule Stripe.CustomerTest do
  # this may be able to be true
  use ExUnit.Case, async: false
  
  # Most of this setup process can be abstracted into the library, but putting
  # it here so that others understand
  setup do
    # Starts a separate process
    #   - That process loads a Plug responder that binds to an available port
    #   - It also seeds an ETS table that it claims ownership of
    #   - The ETS table and Plug responder are bound to this specific test,
    #      so they are isolated to this test and any state manipulation on them
    #      will not affect other tests
    #   - Returns a struct of some form like %Stripe.Test.Server{port: 4515, pid: #PID<0.35.0>}
    {:ok, stripe_server} = Stripe.Test.Server.start()
    
    Application.put_env(:stripity_stripe, :api_base_url, "http://localhost:#{stripe_server.port}")
    
    on_exit fn ->
       #  Cleans up the ETS table and stops the plug responder and owning process
       Stripe.Test.Server.stop(stripe_server)
    end
    
    {:ok, stripe: stripe_server}
  end

  describe "Stripe.Customer.retrieve/1" do
    test "retrieves a customer by ID", %{stripe: stripe} do
      # Uses the Stripe.Test.Customer module to create a new customer in the
      # ETS backed server (essentially, this is a factory method)
      %{id: id} = Stripe.Test.Customer.create(stripe)

      # Makes an actual API request from the high level API through the low level
      # API and through the OS network stack
      {:ok, customer} = Stripe.Customer.retrieve(id)
      
      assert customer.id == id
    end
  end
end
@nkezhaya
Copy link
Contributor

nkezhaya commented Jun 3, 2019

@joshsmith @begedin I started working on something, see here: https://github.com/whitepaperclip/stripe_mock

It starts an http server in your app's test env and tries to respond as accurately as possible to requests. Handles authentication and pagination, and stores everything in memory so no database is needed.

It's extremely primitive right now and I'm not even sure if this is useful to anyone, but it reduced the time required for my test suite to run by like 90%.

@noozo
Copy link

noozo commented Jul 24, 2020

Wouldn't it be easier to define callbacks/behaviours in the code so that people could use Mox to test?

It's a bit of a pain to use a separate server (especially when you consider CI), and the alternative is basically something like Bypass, which is yet another dependency :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants