mixer
mixer copied to clipboard
RuntimeError: Mixer (app.Model): Cannot generate a unique value for user
I'm getting this error in a large Django codebase with hundreds of tests. I believe this happens because all instances that mixer creates are somehow cached and after a while it runs out of dictionary words to create new instances because it compares against the cache and not against the DB (which is obviously empty after each test).
I kind of pinned it down to this loop in main.py and the fact that TypeMixer
derives from TypeMixerMeta
which has "Cache typemixers by scheme." as a docstring makes me think that these instances might act like singletons and are not properly destroyed between tests, so that self.__gen_values
will probably just fill up more and more until the dictionary cannot produce unique items any more.
Is there any workaround for this?
In my case I have a UserProfile
model which has a OneToOneKey to the auth.User
model and I'm usually creating profiles with mixer.blend('user_profile.UserProfile')
which then automatically also tries to mix the user for the profile.
As a workaround I'm now doing this everywhere where I want to mix a UserProfile
:
u = mixer.blend('auth.User')
profile = mixer.blend('user_profile.UserProfile', user=u)
I have no idea why this works. I would assume that the usernames for the auth.User
schema would also get cached and should also result in a "dictionary overflow". Weird.
Hi! Are any updates here?
I got the same issue working with a lot of tests, where user creation is required.
I also ran into this issue:
# Exception
Cannot generate a unique value for user
from django.contrib.auth.models import User
...
# Relevant field in instantiated model
user = models.OneToOneField(User, help_text="...", on_delete=models.CASCADE)
This happens when the retry counter for generating unique values reaches 100.
In main.py (mixer 7.2.2):
counter = 0
try:
while value in self.__gen_values[field_name]:
value = fab()
counter += 1
if counter > 100:
raise RuntimeError("Cannot generate a unique value for %s" % field_name)
self.__gen_values[field_name].add(value)
I collected some data from my test suite. As it can be seen in the first line of the data 23 retries where required with only 33 previously generated users.
Other observations
- It is random, sometimes the suite passes without the error.
- Never occurs when re-running the failed test alone.
- Never occurred when running tests in parallel (16 threads), but probably this only mitigates the problem by using multiple test runners and databases.
- As a workaround I increased the retry counter to 1000.
I expect the field User.username to be the problem as it is unique. I tested the username generator from Faker directly and generated more than 250000 unique usernames before aborting. I am not sure how this can hit 100 retries.