-
Notifications
You must be signed in to change notification settings - Fork 400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
auto_now_add overrides factoryboy params #102
Comments
Hi, That's a built-in "feature" of Django: when a field has You have two options:
class FooFactory(factory.django.DjangoModelFactory):
FACTORY_FOR = models.Foo
@classmethod
def _create(cls, target_class, *args, **kwargs)
foo = kwargs.pop('foo', None)
obj = super(FooFactory, cls)._create(target_class, *args, **kwargs)
if foo is not None:
obj.foo = foo
obj.save()
return obj
from django.utils import timezone
class Foo(models.Model):
foo = models.DateField(default=timezone.now) Note the lack of brackets in I have personnally chosen the second version, which lets me override |
Replacing auto_now_add with default=timezone.now makes it possible to override the field value in tests. See FactoryBoy/factory_boy#102
Quick question - how should this be implemented for auto_add (rather than auto_add_now)? I have an "updated" field, but whether I use models.DateTimeField(auto_now=True) or override the django model .save() method, I can't seem to get FactoryBoy to return the correct value of updated (LazyAttribute(lambda o: o.created + timedelta(hours=1)) or using the _create() method) - it always returns timezone.now(). What's the best way to go here? |
@lmannering I'm not sure about the issue you're having? Basically:
In other words, the way thinks work are:
|
Hi @rbarrois my fault, I wasn't particularly clear - my question is, given your two options on how to best circumvent auto_add_now when using FactoryBoy, what's the best way to fake an "updated" model field (that has either auto_add=True set on the model field or a .save() method with timezone.now), given that order of operations? I've currently monkeypatched the .save() method on the original model before passing to FactoryBoy, is that the best way to do it? |
@lmannering maybe the solution is to use freezegun and circumvent this and other problems all together? |
This makes it possible to override the field value in tests. Refs: - FactoryBoy/factory_boy#102
Here is my way to do it in a universal way with freeze gun https://stackoverflow.com/a/70364787/1731460 |
I know this is an old thread, but there is a third method that I use; override the date without saving… class Foo(models.Model):
created_at = models.DateField(auto_now_add=True)
foo = FooFactory.create()
foo.created_at = date(2001, 1, 1))
# use foo in assertion |
This was quite helpful. In addition to your approach, I found it necessary to include the .save() method to ensure the changes were persisted. |
Say I have a model:
with a trivial factory FooFactory, if I then do:
it prints the current date, not the one I specified. To me this is a violation of principle of least surprise.
The text was updated successfully, but these errors were encountered: