Fl4m3Ph03n1x
How to test Singletons and JCOs?
Background
Some time ago I manifested my dislike for using ETS tables because I saw them as Singletons, which bring a myriad of problems when testing. However @peerreynders linked me to the Just Create One pattern, spearheaded by our dear Uncle Bob.
Theoretical differences
I get the main difference. You can ask an app to create a Singleton a million times, and it will always return the same instance. With JCO, you can’t ask the app to create something a million times - you create it once and that’s it.
Practical differences
But in practice, specially when it comes to testing (which is what I am interested in), they are really both the same. You need a mock (mock as a noun) for each one, and once you bring either of them into your app, you basically forfeit concurrent tests because now you have a global state to worry about - which I dislike very much.
How do you test (or perhaps avoid?) something like a Singleton or a JCO instance and still allow for concurrent tests?
My only idea is to do functional injection, but then I have to pass a (huge) list of dependencies to every function. It is rather discouraging from a design perspective, as you literally need to pass around the whole jungle so you can tell a Gorilla to eat his freaking banana.
Discussion time
Any ideas on how to fix this, testing wise?
Trending in Discussions
Other Trending Topics
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #performance
- #security










First Post!
LostKobrakai
So there are a few considerations: Is the singleton stateful? Can it be mocked for the whole testsuite at once or do you need mocks per single test.
If the latter and it’s stateful then you’re probably out of luck. Even things like Ecto.Sandbox are quite powerful workarounds at best (without explicit ownership passing / injection of dependencies).
But I’m wondering why ETS brought this to the table, as ETS has other usecases as well. Named ETS tables with direct access are singletons, but that’s not all ETS can do.
Most Liked
peerreynders
I don’t agree with this part. The idea behind Just Create One is to replace a global compile time dependency with a local one that is injected at runtime.
If you have 20 tests you can create:
i.e. one for each test so that you can run the tests concurrently.
That of course means that the process under test has to have the reference (handle/pid/name) injected during initialization and the reference has to be held in the process state. By extension any code using the reference will have it passed from the process state.
how big are your functions that they need a (huge) list of dependencies??? This may be symptomatic of an entirely different organizational problem.
Last Post!
peerreynders
To me that is what this is about:
https://elixir-lang.org/getting-started/mix-otp/ets.html#ets-as-a-cache