Fl4m3Ph03n1x

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?

First Post! Switch mode

LostKobrakai

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

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:

  • 20 distinct ETS tables with distinct handles
  • 20 distinct ETS tables with distinct names
  • 20 distinct GenServers with distinct pids
  • 20 distinct GenServers with distinct names

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.

but then I have to pass a (huge) list of dependencies to every function.

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

peerreynders

To me that is what this is about:
https://elixir-lang.org/getting-started/mix-otp/ets.html#ets-as-a-cache

Since each test has a unique name, we use the test name to name our registries. This way, we no longer need to pass the registry PID around, instead we identify it by the test name.

Where Next?

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2976 91332 914
New
byu
@chrismccord : I just saw the Extract AGENTS.md from Phoenix.new into phx.new generator commit to the phoenix project. My initial shotgu...
New
arcanemachine
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
AstonJ
Just a general thread to post chat/news/info relating to AI/ML stuff that may be relevant for Nx now or in the future. Got anything to sh...
New
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
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
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New

Other Trending Topics Top

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
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
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
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

We're in Beta

About us Mission Statement