微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

检查在测试期间是否调用了 pytest 夹具一次

如何解决检查在测试期间是否调用了 pytest 夹具一次

pytest 是否提供 unittest.mock 之类的功能来检查模拟是否真的被调用过一次(或使用某个参数调用一次)?

示例源代码

my_package/my_module.py

from com.abc.validation import Validation


class MyModule:
    def __init__(self):
        pass

    def will_call_other_package(self):
        val = Validation()
        val.do()

    def run(self):
        self.will_call_other_package()

上述源代码的示例测试代码

test_my_module.py

import pytest
from pytest_mock import mocker

from my_package.my_module import MyModule

@pytest.fixture
def mock_will_call_other_package(mocker):
    mocker.patch('my_package.my_module.will_call_other_package')


@pytest.mark.usefixtures("mock_will_call_other_package")
class TestMyModule:

    def test_run(self):
        MyModule().run()
        #check `will_call_other_package` method is called.

        #Looking for something similar to what unittest.mock provide
        #mock_will_call_other_package.called_once

解决方法

如果你想使用一个进行配接的夹具,你可以将配接移动到一个夹具中:

import pytest
from unittest import mock

from my_package.my_module import MyModule

@pytest.fixture
def mock_will_call_other_package():
    with mock.patch('my_package.my_module.will_call_other_package') as mocked:
        yield mocked
    # the mocking will be reverted here,e.g. after the test


class TestMyModule:

    def test_run(self,mock_will_call_other_package):
        MyModule().run()
        mock_will_call_other_package.assert_called_once()

请注意,您必须在测试中使用fixture 参数。仅使用 @pytest.mark.usefixtures 不会让您访问模拟本身。如果您不需要在所有测试中访问模拟(或在夹具中使用 autouse=True),您仍然可以使用它在类中的所有测试中有效。

另请注意,这里不需要 pytest-mock - 但正如@hoefling 所提到的,使用它可以使夹具更好地可读,因为您不需要 with 子句:

@pytest.fixture
def mock_will_call_other_package(mocker):
    yield mocker.patch('my_package.my_module.will_call_other_package')

顺便说一句:您不需要导入 mocker。固定装置按名称查找,如果安装了相应的插件,则自动可用。

,

你可以试试这个:

import pytest

from my_package.my_module import MyModule

def test_run(mocker):
    mocker.patch('my_package.my_module.will_call_other_package')
    MyModule().run()
    mock_will_call_other_package.assert_called_once()
,

首先,您可能不需要像 pytest_mock 这样的外部库的负担,因为 pytest 已经让您使用 integration with unittest

您也不需要使用 usefixtures,因为每当您需要一个装置时,您只需在您的测试方法中接收它。

基于您自己的代码的理想场景如下所示:

import pytest
from unittest.mock import patch

from com.abc.validation import Validation


class MyModule:
    def __init__(self):
        pass

    def will_call_other_package(self):
        val = Validation()
        val.do()

    def run(self):
        self.will_call_other_package()


@pytest.fixture
def call_other_module():
    with patch("my_package.my_module.MyModule.will_call_other_package") as _patched:
        yield _patched


class TestMyModule:
    def test_run_will_call_other_package(self,call_other_module):
        call_other_module.assert_not_called()
        obj = MyModule()
        call_other_module.assert_not_called()
        obj.run()
        call_other_module.assert_called_once()

此外,如果您想确保您确实对目标 MyModule.will_call_other_package 进行了修补,请像这样修改您的测试:

class TestMyModule:
    def test_run_will_call_other_package(self,call_other_module):
        call_other_module.assert_not_called()
        obj = MyModule()
        call_other_module.assert_not_called()
        obj.run()
        call_other_module.assert_called_once()
        assert False,(MyModule.will_call_other_package,call_other_module)

你会看到类似的东西:

AssertionError: (<MagicMock name='will_call_other_package' id='140695551841328'>,<MagicMock name='will_call_other_package' id='140695551841328'>)

如您所见,两个对象的 id 相同,证实我们的实验成功。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。