BitGonzo
I’ve started to test my application and immediately run into the mock debate. Just done reading:
The above suggests using explicit contracts and config variables to manage environment-specific dependencies initially, and then goes on to suggest the simpler method of injecting dependency directly.
However, my current method is a little different. I am using explicit contracts and delegation such as:
config :myapp, request_client: MyApp.Tesla.Request
defmodule MyApp.Request do
@client Application.get_env(:myapp, :request_client)
defdelegate make, to: @client
@callback make(etc) :: etc
end
defmodule MyApp.Tesla.Request do
@behaviour MyApp.Request
use Tesla
plug Tesla.Middleware.Retry, delay: 1000, max_retries:: 3
def make do
# perform request, return response
end
end
This gives me a common interface and call MyApp.Request.make, while also giving me the ability to switch out the client with configuration, which I will use during testing.
Does this look sensible? Is there something inherently wrong with the above approach or, in your opinion, an improvement?
The second question is about testing MyApp.Tesla.Request – perhaps I can switch out the client I use in testing, but surely I still need to test that my Tesla request is configured/running properly.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
AmberBit
This looks okay. You can also use mox that basically does the same thing + has verifications/assertions you can use in tests.
BitGonzo
Was just reading through
moxdocumentation then. I’ll see how far I get in my tests.hubertlepicki
Maybe examples here will make it a bit more clear: Mox
BitGonzo
Not entirely sure how
moxis working, but I have this:..passes. But my type specifies integer and I have another function defined in my
@callbackwhich hasn’t been defined in theExampleMock(though those guarantees don’t appear to exist anyway when using@behaviourin derived modules). Are those types (integer(), etc) just for documentation purposes? They don’t have any effect beyond that?Seems a shame to have all of this ceremony without the guarantees. Seem more like guidelines than explicit contracts?
idi527
I think they can be checked by dialyzer.
BitGonzo
Ahh I see. I’ve not delved into that yet.
hubertlepicki
Yep, these are not checked by Elixir compiler, so serve as documentation only unless you use dialyzer.
BitGonzo
Fair enough. I’d like to use dialyzer but that’s a whole can of worms I’m unwilling to open. Included it in a project and it’s coming up with all kinds of non-issues/noise, even with warnings disabled. Not enough time in the day to be fighting with another tool
@specis good enough for me.kokolegorille
It is not that complicate to use dialyzer with dialyxir… just add
to your deps.
Then run (it take some time at first, but then it’s ok)
I had to ignore some warnings coming from some Erlang sources included in my project. To configure this is also simple, just add to mix.exs, in the project section.
and create a file dialyzer.ignore-warnings containing the rules You want to ignore.
BitGonzo
Yep, that’s what I tried.
I just can’t be doing with cryptic stuff like the following about code which works:
`
The pattern {'ok', Vresponse@1} can never match the type #{'__client__':=fun(), '__module__':=atom(), '__struct__':='Elixir.Tesla.Env', 'body':=_, 'headers':=#{binary()=>binary()}, 'method':='delete' | 'get' | 'head' | 'options' | 'patch' | 'post' | 'put' | 'trace', 'opts':=[any()], 'query':=[{atom() | binary(),binary() | [{atom() | binary(),binary() | [{_,_}]}]}], 'status':=integer(), 'url':=binary()}`
Well it can match the type because it does. I would love to have this checking if it worked.
Also:
:0: Unknown function 'Elixir.GenStage':start_link/2 :0: Unknown function 'Elixir.Request':make/1 lib/gen_stage.ex:1: Callback info about the 'Elixir.GenStage' behaviour is not available..and in my templates (using
slime):/templates/layout/app.html.slim:1: Guard test _@7::bitstring() =:= 'false' can never succeed