I have a model in django that has a foreign key to another model, and during unit testing I want to avoid tight-coupling of the two models and create a stub for the other model that will return different values each time.
class Moon(models.Model): def phase(self): # some extremely complex code class Wolf(models.Model): moon = models.ForeignKey(Moon) mood = models.CharField() def update_mood(self): if (self.moon.phase == 'new moon'): self.mood = "good" if (self.moon.phase == 'waxing crescent'): self.mood = "hopefull" ...
Example for the above:
w = Wolf() m = Moon() # m.phase = 'new moon' w.moon = m w.update_mood() w.mood # 'good'
Now I want to test the Wolf().moon property after I do an update_mood() call, without actually touching the Moon model at all - because its a very complex model that goes out into all kinds of external systems to figure out its phase.
Usually I would use monkey-patching for this, but since .mood is a property ... I can't really assign to it in a monkey-patching way.
With a bit of digging, stumbled on the model add_to_class() method that does proper monkey patching and can override foreign key properties on a model.
Example of usage:
def get_phase(self): return self._phase
def set_phase(self, phase): self._phase = phase
phase = property(get_phase, set_phase)
# this bit is the answer to the question above
w = Wolf()
w.moon.phase = 'new moon'
assert w.mood == 'good'
w.moon.phase = 'waxing crescent'
assert w.mood == 'hopefull'
For the sake of testing, you could override (monkey patch, if you want to use it in test environment only) __ getattribute__.
In __ getattribute__ check if the property moon is called, return the value or set the value in a temporary var.