Django 测试:如何存根 model.ForeignKey 属性?

发布于 2024-10-29 05:12:46 字数 804 浏览 11 评论 0原文

我在 django 中有一个模型,它有另一个模型的外键,在单元测试期间,我想避免两个模型的紧密耦合,并为另一个模型创建一个存根,每次都会返回不同的值。

人为的示例:

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"
        ...

上面的示例:

w = Wolf()
m = Moon()
# m.phase = 'new moon'
w.moon = m
w.update_mood()
w.mood   # 'good'

现在我想在执行 update_mood() 调用后测试 Wolf().moon 属性,而不实际接触 Moon 模型 - 因为它是一个非常复杂的模型,涉及各种类型外部系统以确定其相位。

通常我会为此使用猴子修补,但由于 .mood 是一个属性......我不能真正以猴子修补的方式分配给它。

帮助。

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.

Contrived example:

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.

Help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

送你一个梦 2024-11-05 05:12:46

经过一番挖掘,偶然发现了模型的 add_to_class() 方法,该方法可以进行适当的猴子修补,并且可以覆盖模型上的外键属性。

使用示例:

class FakeMoon(object):
    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
Wolf.add_to_class("moon", FakeMoon())

w = Wolf()

w.moon.phase = 'new moon'
w.update_mood()
assert w.mood == 'good'

w.moon.phase = 'waxing crescent'
w.update_mood()
assert w.mood == 'hopefull'

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:

class FakeMoon(object):
    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
Wolf.add_to_class("moon", FakeMoon())

w = Wolf()

w.moon.phase = 'new moon'
w.update_mood()
assert w.mood == 'good'

w.moon.phase = 'waxing crescent'
w.update_mood()
assert w.mood == 'hopefull'
咽泪装欢 2024-11-05 05:12:46

为了测试的目的,您可以覆盖(monkey patch,如果您只想在测试环境中使用它)__ getattribute__。

在 __ getattribute__ 中检查是否调用了 Moon 属性,返回该值或在临时变量中设置该值。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文