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

Testing with Tesla.Mock #238

Closed
chulkilee opened this issue Aug 26, 2018 · 4 comments
Closed

Testing with Tesla.Mock #238

chulkilee opened this issue Aug 26, 2018 · 4 comments
Labels

Comments

@chulkilee
Copy link
Contributor

In integration tests, or unit tests for component talking to multiple endpoints, mocking responses from multiple Tesla clients is required.

Example: CRM.Customer.Sync module (in CRM application) uses Foo.Api and Bar.Api, two different Tesla-based clients.

How can it be done with Tesla.Mock?

Another way to achieve is to use mox but it requires declaring behaviors for all API client, and then implement helper functions for bad cases. This is more "right" approach (since other code using API wrapper should not care about actual HTTP response).

Also I understand it's better to refactor the code to isolate interaction, but it's not always possible for various reasons :) Also still using same Tesla.Mock for different components doesn't look right to me.

So.. I'd like to hear about what's possible right now, and thoughts on supporting it, etc.

@teamon
Copy link
Member

teamon commented Aug 28, 2018

There are no differences when testing one or multiple clients. You can compose mock functions like:

Tesla.Mock.mock fn ->
  %{url: "http://foo" <> _} -> ...
  %{url: "http://bar" <> _} -> ...
  _ -> {404, [], ""}
end

@chulkilee chulkilee changed the title Testing multiple clients with Tesla.Mock Testing with Tesla.Mock Aug 28, 2018
@chulkilee
Copy link
Contributor Author

Thanks a lot for the answer - I see that's possible with single adopter.

(updated the title to cover more questions on tests)

However, for library maintainer, how can I expose this mock behavior correctly? Do you think it's better to use mox in that case?

Example: I wrote ex_force for Salesforce API wrapper. I need to use it from another app (let's say CRM) - and I just want to test different API responses.

  • Option 1: use Tesla.mock for ExForce in CRM app config - then test code in CRM needs to use Tesla.Mock with actual api responses, which is duplicate from unit test in ExForce, and it is more than CRM
  • Option 2: use mox - use mock ExForce Client, so that it does not actually call client
    • It requires declaring behavior

Also I don't think it's possible to swap adapter with build_client (which I always use). So I'm right now using using bypass with dynamic client.

@teamon
Copy link
Member

teamon commented Aug 28, 2018

In case of a library I'd recommend having a well defined (and spec'd) interface and then use mox to mock on the library level. However, there are sometimes cases when it is easier to mock on the http level - it really depends on the complexity. Recently I had a case of reading a lot of data from multiple different APIs and I went with tape/vcr solution - test again real endpoints and record the responses.

Very basic implementation of such adapter can be find in the cookbook.

Swapping adapter in runtime is possible (see #219 (comment)) but not pleasant nor properly documented :|

@teamon
Copy link
Member

teamon commented Sep 7, 2018

For reference, changing adapter in runtime will soon be possible #244.

@teamon teamon closed this as completed Sep 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants