jyotigautam
I have a Product schema which has a UPI(unique product identifier) eg. A985748BNG6784C . This is an autogenerated unique product identifier.
I have a function upi_generate() which calls another external function gen_nano_id() to generate this random unique id.
If by chance, the id generated by gen_nano_id() has already been generated, the function upi_generate() calls itself recursively till the time gen_nano_id() generates a unique id. Thus generating a unique UPI .
gen_nano_id() can sometimes return duplicate ids and for that purpose I have written the below code with recursive call.
def gen_nano_id() do #external function
Nanoid.generate(10, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
end
# TODO: write test case for this
def upi_generate() do # required function
upi = "A" <> gen_nano_id() <> "C"
case get_product_with_upi(upi) do
nil ->
upi
_ ->
upi_generate()
end
end
# Check if product with upi already exists
defp get_product_with_upi(upi) do
from(p in "snitch_products", select: p.upi, where: p.upi == ^upi)
|> Repo.one()
end
Now, I have to test the id regeneration logic for duplicate ids.
My testing approach involves following logic. Create two products with duplicate UPI and try to reach the _ part of the case comparison.
For this purpose, I have mocked(I don’t control the behaviour of this function) the gen_nano_id() .
Now, the problem that I am facing is mocking results in creation of always the same ids no matter what and I go in an infinite loop.
I am not able to figure out a way to reach the exit condition(nil) part of case comparison with this mocking approach of gen_nano_id .
Trending in Questions
Other Trending Topics
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
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










Marked As Solved
dimitarvp
First, here’s a stateful
Agentthat holds a counter and a simple logic that forces it to return the same value several times, before starting to return random values afterwards. Like this:Then let’s compose a test class:
Put these modules in a single Elixir file and then run
NanoidTestWithMock.test()in aniexsession.(Or add the above expression at the bottom of the file and just tell Elixir to run it.)
You should see something like this:
Hope that helps.
EDIT: As for mocking the Nanoid library itself, I’ll leave that exercise to you.
Also Liked
gausby
Don’t mock it; instead pass in the random uuid as an argument; have it return something like
{:error, :uuid_already_in_use}in the function generating the upi so you can try with a new one if the UUID should already be taken.In general I think it is a good idea to pass this kind of data into functions, including timestamps, as it will make testing a lot easier.
jyotigautam
Thanks for suggesting the approach. This nicely tests the scenario of duplicate UPIs.