I have a class, for which I would like to write a factory using FactoryBoy
. However, this class doesn't produce its instances using the __init__
method, but rather a number of factory methods:
class MyClass:
def __init__():
self.field = None
self.is_valid = False
@staticmethod
def from_str(arg):
inst = MyClass()
inst.field = arg
inst.is_valid = True
return inst
Is there a way to write a FactoryBoy factory such that it uses this static factory method instead of passing the fields to MyClass
initialiser?
The way to do this is to override the _build(...)
or _create(...)
classmethod on your Factory
subclass.
Assuming the arg
in your class is described by the text
parameter of your factory:
class MyFactory(factory.Factory):
class Meta:
model = MyClass
@classmethod
def _create(cls, model_class, *args, text, **kwargs):
return model_class.from_string(text)
text = factory.Sequence("some-input:{}".format)
With that code, calling MyFactory()
would call MyClass.from_string("some-input:0")
; and calling MyFactory(text="some-data")
will return the value from MyClass.from_string("some-data")
.
If you have lots of classes using that same mechanism, you may even add a custom abstract factory to share that def _create
declaration:
class FromStringFactory(factory.Factory):
class Meta:
abstract = True
@classmethod
def _create(cls, model_class, *args, text, **kwargs):
return model_class.from_string(text, **kwargs)
class SomeClassFactory(FromStringFactory):
class Meta:
model = SomeClass
text = factory.Faker("country")