首页 > 编程问答 >如何确保 return_value 类型与被模拟方法的类型提示兼容

如何确保 return_value 类型与被模拟方法的类型提示兼容

时间:2024-07-22 10:30:00浏览次数:12  
标签:python unit-testing python-typing

假设我有一个单元测试,它模拟一些类 A 以返回自定义值。我希望能够更改模拟 A 实例返回的值,但我绝对不想意外更改返回值的类型并导致我的测试无意中检查错误的内容。

例如,采用下面的代码:

import datetime
import unittest
import unittest.mock

class A:
    def foo(self, getter):
        return getter.get_time() == '2020-01-01'

class Getter:
    def get_time(self) -> datetime.datetime:
        return datetime.datetime(2020,1,1)

@unittest.mock.patch("__main__.Getter", autospec=True)
class MyTestCase(unittest.TestCase):

    def test_case_1(self, Getter):
        getter = Getter()
        getter.get_time.return_value = '2020-01-01'
        
        a = A()
        self.assertTrue(a.foo(getter))

test_case = MyTestCase()
test_case.test_case_1()

在上面的单元测试中,我们应该检查时间是否匹配“2020-01-01”,但是我们将 return_value of get_time 设置为一个字符串,因此,即使违反了 get_time (返回a datetime )的返回类型提示,测试也会成功,因此实际代码永远无法工作。有没有办法让unittest/mock 找到这个并告诉我我错误地设置了 return_type 一个与方法上的类型提示不兼容的值?


Python 中的 unittest.mock 库本身没有内建的方法来强制执行返回值类型提示。 然而,你可以结合使用其它工具来达到目的。

1. 使用类型检查器,比如 MyPy:

MyPy 可以分析你的代码,包括单元测试,并验证类型提示是否被遵守。如果你设置一个返回值与被模拟方法的类型提示不符,MyPy 将会报告一个错误。

  • 安装 MyPy: bash pip install mypy

  • 运行 MyPy: bash mypy your_module.py

在你的例子中,MyPy 会将 getter.get_time.return_value = '2020-01-01' 标记为错误,因为它违反了 get_time 的返回值类型提示 ( datetime.datetime )。

2. 使用模拟库,支持类型检查,比如 pytest-mock:

pytest-mock 是一个 pytest 插件,它提供了增强的模拟功能,包括对类型提示的基本支持。当与类型检查器(如 MyPy)一起使用时,它可以帮助识别模拟返回值类型的不匹配。

  • 安装 pytest-mock: bash pip install pytest-mock

  • 例子:

    ```python import datetime import pytest

    class A: def foo(self, getter): return getter.get_time() == '2020-01-01'

    class Getter: def get_time(self) -> datetime.datetime: return datetime.datetime(2020,1,1)

    @pytest.mark.parametrize("mock_return_value", [ datetime.datetime(2020, 1, 1), # 正确的类型 '2020-01-01' # 错误的类型 ]) def test_case_1(self, mocker, mock_return_value): mocker.patch(" main .Getter.get_time", return_value=mock_return_value) a = A() assert a.foo(Getter()) ```

    在这个例子中,我们使用 pytest-mock 来修补 Getter.get_time 方法,并使用参数化测试来测试不同的返回值,包括正确和错误的类型。MyPy 会将错误类型的返回值标记为错误。

通过结合使用类型检查器和像 pytest-mock 这样的库,你可以在编写单元测试时获得更好的类型安全性,并尽早捕获潜在的错误。

标签:python,unit-testing,python-typing
From: 69029431

相关文章

  • Python学习计划——2.4列表推导式(List Comprehensions)
    列表推导式是Python的一种简洁且强大的语法,用于生成新的列表。它可以用更少的代码、更清晰的方式来创建列表,特别是在处理简单的循环和条件操作时。1.基本语法列表推导式的基本语法如下:[expressionforiteminiterable]expression:表达式,计算结果用于生成列表的元素。ite......
  • Python学习计划——2.3常用内置函数(len, max, min, sum, etc.)
    Python提供了许多内置函数,用于简化对数据结构的操作。以下是一些常用的内置函数及其详细说明。1.len()len()函数用于返回对象(如列表、元组、字符串、字典等)的长度(元素个数)。示例:#列表fruits=["apple","banana","cherry"]print(len(fruits))#输出:3#元组c......
  • 哪个 Python 框架可以在 Google Collab 中显示和更改图像?
    我希望能够在使用GoogleCollab时为RL绘制高fps的位图。我现在可以使用OpenCV绘制图像cv2_imshowgoogle替换cv2.imshow但是,它无法替换现有图像,它下面绘制了新的我能够在替换imshow函数中使用一些JavaScript来修复它。但刷新率约为......
  • VSCode 自动建议 python 导入而不依赖 Intellisense
    我正在使用Transformer中的AutoModel之类的对象,并且经常遇到自动导入建议无法找到的对象。我总是希望VSCode建议“从Transformer中执行”,而不是费心寻找它找不到的原因每当看到未定义的“AutoModel”时,都会导入AutoModel”,因此无需扫描任何python导入目录。这......
  • 如何使用Python计算位移自相关函数?
    我正在使用python来分析粒子的异常扩散。我已经得到了粒子轨迹的位移,我想计算并绘制位移自相关与滞后时间t的关系。我认为可能存在使用t和位移(如deltar)的自相关函数的一般函数,但我不能没找到。我可以得到函数或代码吗?可以使用numpy和matplotlib库在Python......
  • 一天一点点,第四天Python基础
    第一天:一天一点点。Python基础-CSDN博客第二天:一天一点点,接上章Python基础-CSDN博客第三天:一天一点点,第三天Python基础(循环语句)-CSDN博客推导式推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。推导式是一种强大且简洁的语法,适用于生......
  • Python - for循环不使用正则表达式附加数组
    以下代码从URL获取版本号,然后对于每个版本号,转到该版本号的页面并使用文件名的特定模式填充数组。生成的数组应包含每个版本号的文件名列表,但它似乎只包含早期版本(2.6)。使用print语句,我可以看到代码的工作原理是它获取sha256sums.asc文件-所有这些文件,所有版本。我猜......
  • 使用 callable_iterator (re.finditer) 导致 Python 冻结
    我有一个为文本的每一行调用的函数。deftokenize_line(line:str,cmd=''):matches=re.finditer(Patterns.SUPPORTED_TOKENS,line)tokens_found,not_found,start_idx=[],[],0print(matches)formatchinmatches:pass#Rest......
  • Python 的 time.sleep - 永远不会醒来
    我认为这将是那些简单的问题之一,但它让我感到困惑。[停止媒体:我是对的。找到了解决方案。查看答案。]我正在使用Python的单元测试框架来测试多线程应用程序。很好而且很直接-我有5个左右的工作线程监视一个公共队列,以及一个为它们制作工作项的生产者线程......
  • python中使用mitmproxy的http模块出错
    我有一个使用mitmproxyhttp函数的代码,它在这里惨败:defmain(stdscr):try:parser=argparse.ArgumentParser(description='NetSourNetworkAnalyzer')parser.add_argument('--proxy',action='store_true',help='EnableH......