python - 如何在 Python 单元测试中模拟一个类?

标签 python testing mocking

我有一个类:

class A:
    __init__(self):
        self.b = B()

   def is_authorized(self)
      name = self.b.get_name()

      if name == 'admin':
          return True
      else:
          return False

我想编写一个单元测试来测试 is_authorized 方法。问题是它需要一个 B 类的实例,因为它需要网络连接和其他东西,所以单独构造起来非常复杂。我如何模拟此类并提供仅具有 get_name 方法的内容。这样我就可以创建 A 类并测试该方法。

最佳答案

通过使用mock库,您可以修补 B 类并将其替换为 MagicMock() 对象。 mock 库正是为完成这些工作而设计的,并打破了有问题的对象或真实资源的硬依赖。

在您的简单示例中,完整的测试将是:

module_a.py

class B():
    def __init__(self):
        print("The awful B class!!!")

    def get_name(self):
        print("The awful B.get_name() method!!!")


class A():
    def __init__(self):
        self.b = B()

    def is_authorized(self):
        name = self.b.get_name()
        if name == 'admin':
            return True
        else:
            return False

module_a_test.py

import unittest
from unittest.mock import patch
from module_a import A


class MyTestCase(unittest.TestCase):

    # patch B class in a_module by a MagicMock instance
    # mock_b_constructor passed to test method
    @patch("module_a.B")
    def test_a(self, mock_b_constructor):
        # B() return value will be the B() instance assigned to a.b property
        mock_b = mock_b_constructor.return_value
        # Now start test:
        a = A()
        # Ok! b is our mock...
        self.assertIs(a.b, mock_b)
        # Not authorized
        self.assertFalse(a.is_authorized())
        mock_b.get_name.return_value = 'admin'
        # Yeah!!! we are admin
        self.assertTrue(a.is_authorized())
        # Sanity check
        mock_b.get_name.return_value = 'guest'
        self.assertFalse(a.is_authorized())

Patch将只为您的测试方法上下文而存在。这是一个简单直接的示例,说明如何使用 mock 中的模拟和补丁,但实际情况可能会稍微复杂一些。

关于python - 如何在 Python 单元测试中模拟一个类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28074697/

相关文章:

python - 奇怪的错误——有时显示有时不显示

python - 我应该在 python 的类中使用我自己的属性吗?

javascript - Protractor js 测试工作流程

.net - 如何模拟 ASP.NET ServerVariables ["HTTP_HOST"] 值?

ruby - 如何模拟与外部服务的连接

Python:使用 Flask 模拟补丁错误

python - boost python C4244 警告

python - 在Python中为游戏添加计分时钟

java - 我应该如何在每次测试前重置 JPA 控制的数据库?

python - mercurial:在每次提交时自动运行远程回归测试