如何在 Python 中模拟类中的属性

DLS*_*DLS 6 python unit-testing mocking pytest

这是我的第一个文件 user.py

from account import Account    
class User:
   def __init__(self, id):
       self.id = id
       self._account = None

   @property
   def account(self):
       if not self._account:
          self._account = Account(self.id)

       return self._account

   @property
   def has_discount(self)
       return self.account.discount_id > 0
Run Code Online (Sandbox Code Playgroud)

我有一个名为 account.py 的第二个文件

class Account:
    def __init__(self, user_id):
        # some process to load DB data
        self.account = load_account(user_id)
        # do something after this to initialize account properties like discount, etc

    @property
    def discount_id(self):
       return self.discount_id
Run Code Online (Sandbox Code Playgroud)

我的目标是测试 user.py。我想要做的一件事是在 user.py 中为“has_discount”属性装饰器模拟 Account 对象。我想测试不同的场景,其中 has_discount 将返回 0 或任何其他数字。

我如何使用补丁来做到这一点,我可以在其中模拟 User 类中的 Account 对象以返回自定义值,以便我可以尝试不同的测试?

Ilj*_*ilä 5

因为user模块导入Account到它自己的命名空间中,所以修补必须在那里完成,而不是account模块本身。换句话说,您必须暂时更改模块Account中的名称user所指的内容:

from user import User
from unittest.mock import patch

with patch('user.Account') as MockAccount:
    MockAccount.return_value.discount_id = 1
    u = User(1)                             
    print(u.has_discount)
    # True

with patch('user.Account') as MockAccount:
    MockAccount.return_value.discount_id = 0
    u = User(1)
    print(u.has_discount)
    # False
Run Code Online (Sandbox Code Playgroud)

我想测试 has_discount 将返回 0 或任何其他数字的不同场景。

在当前的实现User.has_discount中将始终返回Trueor False。你的意思Account.discount_id