我有一个Django模型的客户经理,该模型会覆盖create
方法以保存一些相关对象:
class CustomManager(models.Manager):
def create(self, amount, user, description):
txn = self.get_query_set().create(user, description)
txn.budget_transactions.create(amount)
return txn
我的问题是:如何模拟对txn.budget_transactions.create
的调用以引发异常?
budget_transactions
对象的txn
属性是django.db.models.fields.related.RelatedManager
的实例。使用mock.patch
来模拟这个类不起作用,因为它是动态声明的 - 它无法直接导入。
有谁知道怎么做?
答案 0 :(得分:6)
您不能将RelatedManager设置为模拟对象的原因是因为django已覆盖对象上的 set 方法。因此,虽然看起来模拟设置正确,因为没有抱怨,但它实际上是静默地将budget_transactions
设置回RelatedManager。因此,如果您确实需要返回模拟,那么您将需要覆盖返回RelatedManager的 get 方法,并返回一个模拟对象。
应该最终看起来像:
@mock.patch('django.db.models.fields.related.ForeignRelatedObjectsDescriptor.__get__')
def test_campaign_cancel(self, mock_manager):
mock_manager.return_value = mock.MagicMock()
mock_manager.return_value.create = Exception('Boom!')
话虽如此,这种方法存在许多缺陷,因为它将覆盖核心django方法,现在 ALL RelatedManagers将返回一个模拟对象。根据我迄今为止所经历的情况,探索其他选择可能更容易。