I noticed a weird bug in my app that I stumbled upon accidentally. I was able to create a new wishlist but was unable to access it using the public link.

The wishlist url was https://wishlist.itsybit.se/wishlist/1c1ac2ba-e86e-43a6-ace4-820e9ed37cf5 and the public url was https://wishlist.itsybit.se/wishlist/public/Nxl5CiAEcjkaBXsFbDM/KyweflNREg==
It took a while but eventually I saw that the route was truncating the public id because the id itself had a forward slash in it.
Figuring out the fix was fairly straightforward but to build the fix using TDD. Basically making a test to replicate the bug, and then building the fix.
This was a little bit tricky to do because there is an element of chance in the bug happening since it all depends on the Guid that is dynamically generated on wishlist creation and how the encoded public key looks like.
I had seeded integrations tests from when I had not implement an actual persistence mechanism. Once I did, I created integrated tests that used a local version of azure for all the cases and I had originally thought of phasing out the tests where I seeded the content. Lucky I didn’t since I can now use these to create a test for this specific case.
I also needed to find a Guid that would get encoded to a shortkey with a / and use that in the seeded repository.

I’m glad I decided to write the tests because I got to discover and debug easier another issue where for some reason %2F is not decoded when it is passed as a route parameter in asp.net URL Decode in Web API pipeline doesn’t decode %2F to / · Issue #23633 · dotnet/aspnetcore · GitHub
So yes, in conclusion, while end to end tests are great, there are definitely specific cases where it is helpful to be able to mock things that one would normally not have any control of. That’s not just responses from external services but also things like time, dynamically generated IDs, etc. There are different ways of enabling this, in your tests. For my case, it was just easiest to reuse my old implementation of my inmemory repository with some seeded content. Ideally, it would have been great to abstract away the Guid generation to an interface so that it becomes mockable in the tests. However, i thought to KISS this time 😬
Leave a comment