如何模拟你的功能? 我不知道如何在Python中模拟我的函数,我试着寻找一些代码,但似乎没有用,考虑一下这个布局: | project.py | tests.py

如何模拟你的功能? 我不知道如何在Python中模拟我的函数,我试着寻找一些代码,但似乎没有用,考虑一下这个布局: | project.py | tests.py,python,Python,project.py: tests.py: 因此,python3 tests.py: 正如您所看到的,test\u os\u urandom\u mocked是可以的,但是我尝试模拟foobar函数的所有其他测试都失败了,不知道为什么,请任何人解释一下是否可以这样做?您可以通过模块引用修补过的函数来实现这一点: import unittest from unittest.mock import patch import os import project def os_urandom_mock

project.py:

tests.py:

因此,python3 tests.py:


正如您所看到的,test\u os\u urandom\u mocked是可以的,但是我尝试模拟foobar函数的所有其他测试都失败了,不知道为什么,请任何人解释一下是否可以这样做?

您可以通过模块引用修补过的函数来实现这一点:

import unittest
from unittest.mock import patch
import os
import project

def os_urandom_mock():
    return 'mocked'

def foobar_mock():
    return 'mocked'


class TestProject(unittest.TestCase):

    @patch('os.urandom', side_effect=os_urandom_mock)
    def test_os_urandom_mocked(self, os_urandom_mocked):
        self.assertEqual(os.urandom(), 'mocked')

    @patch('project.foobar', side_effect=foobar_mock)
    def test_foobar_mocked(self, foobar_mocked):
        self.assertEqual(project.foobar(), 'mocked')

    @patch('project.foobar')
    def test_foobar_mocked_another(self, foobar_mocked):
        foobar_mocked.return_value = 'mocked'
        self.assertEqual(project.foobar(), 'mocked')

    def test_foobar_mocked_last_try(self):
        with patch('project.foobar') as foobar_mocked:
            foobar_mocked.return_value = 'mocked'
            self.assertEqual(project.foobar(), 'mocked')

unittest.main()
这里需要注意的关键是,当您给patch一个字符串时,它将替换该路径上的引用。这种行为得到了很好的证明。谢谢你的链接

按照现在的代码,测试文件中的foobar引用了原始函数,因为您是在补丁安装到位之前导入的。相反,如果您通过模块引用它,您将始终使用模块的引用

或者,您可以按照注释中的建议执行操作,并让修补程序替换当前范围内的引用,而不是原始模块中的引用:

import unittest
from unittest.mock import patch
import os
from project import foobar

def os_urandom_mock():
    return 'mocked'

def foobar_mock():
    return 'mocked'


class TestProject(unittest.TestCase):
    @patch(__name__ + '.foobar', side_effect=foobar_mock)
    def test_foobar_mocked(self, foobar_mocked):
        self.assertEqual(foobar(), 'mocked')

    @patch(__name__ + '.foobar')
    def test_foobar_mocked_another(self, foobar_mocked):
        foobar_mocked.return_value = 'mocked'
        self.assertEqual(foobar(), 'mocked')

    def test_foobar_mocked_last_try(self):
        with patch(__name__ + '.foobar') as foobar_mocked:
            foobar_mocked.return_value = 'mocked'
            self.assertEqual(foobar(), 'mocked')

unittest.main()
请注意,在大多数情况下,您将修补被测试模块导入的内容,而不是在测试中直接调用修补后的函数。在这种情况下,事情往往会更干净:

asdf.py:

project.py:

tests.py:


您可以通过模块参考已修补的功能来实现这一点:

import unittest
from unittest.mock import patch
import os
import project

def os_urandom_mock():
    return 'mocked'

def foobar_mock():
    return 'mocked'


class TestProject(unittest.TestCase):

    @patch('os.urandom', side_effect=os_urandom_mock)
    def test_os_urandom_mocked(self, os_urandom_mocked):
        self.assertEqual(os.urandom(), 'mocked')

    @patch('project.foobar', side_effect=foobar_mock)
    def test_foobar_mocked(self, foobar_mocked):
        self.assertEqual(project.foobar(), 'mocked')

    @patch('project.foobar')
    def test_foobar_mocked_another(self, foobar_mocked):
        foobar_mocked.return_value = 'mocked'
        self.assertEqual(project.foobar(), 'mocked')

    def test_foobar_mocked_last_try(self):
        with patch('project.foobar') as foobar_mocked:
            foobar_mocked.return_value = 'mocked'
            self.assertEqual(project.foobar(), 'mocked')

unittest.main()
这里需要注意的关键是,当您给patch一个字符串时,它将替换该路径上的引用。这种行为得到了很好的证明。谢谢你的链接

按照现在的代码,测试文件中的foobar引用了原始函数,因为您是在补丁安装到位之前导入的。相反,如果您通过模块引用它,您将始终使用模块的引用

或者,您可以按照注释中的建议执行操作,并让修补程序替换当前范围内的引用,而不是原始模块中的引用:

import unittest
from unittest.mock import patch
import os
from project import foobar

def os_urandom_mock():
    return 'mocked'

def foobar_mock():
    return 'mocked'


class TestProject(unittest.TestCase):
    @patch(__name__ + '.foobar', side_effect=foobar_mock)
    def test_foobar_mocked(self, foobar_mocked):
        self.assertEqual(foobar(), 'mocked')

    @patch(__name__ + '.foobar')
    def test_foobar_mocked_another(self, foobar_mocked):
        foobar_mocked.return_value = 'mocked'
        self.assertEqual(foobar(), 'mocked')

    def test_foobar_mocked_last_try(self):
        with patch(__name__ + '.foobar') as foobar_mocked:
            foobar_mocked.return_value = 'mocked'
            self.assertEqual(foobar(), 'mocked')

unittest.main()
请注意,在大多数情况下,您将修补被测试模块导入的内容,而不是在测试中直接调用修补后的函数。在这种情况下,事情往往会更干净:

asdf.py:

project.py:

tests.py:


事实上,我真正想做的是模拟post_save django信号,所以

事实上,我真正想做的是模拟post_save django信号,所以

尝试返回值而不是副作用。同样的结果,无!='模拟“尝试返回值而不是副作用。结果相同,无!=”mocked'这将起作用,但您不需要通过模块引用函数。这意味着您必须将所有的导入都更改为模块导入以进行任何模拟。您需要通过查找对象的位置来引用它。例如,在他最初的测试中,我非常确定他可能会使用@patch'foobar,并且它会起作用。更多信息:谢谢。我不知道你不需要参考模块就可以做到这一点。在这种情况下,你实际上不能用这种方式修补“foobar”,但这仅仅是因为修补程序的工作方式。它需要一个指向要替换的引用的完全限定路径。我会继续更新我的答案,并附上一些关于这个的注释。啊,你说得对。修补程序需要点分隔的模块字符串。但是,试试这个:@patch\uuuu name\uuuuu+'.foobar',它可以修补您当前所在模块中的内容。干杯这将起作用,但您不需要通过模块引用函数。这意味着您必须将所有的导入都更改为模块导入以进行任何模拟。您需要通过查找对象的位置来引用它。例如,在他最初的测试中,我非常确定他可能会使用@patch'foobar,并且它会起作用。更多信息:谢谢。我不知道你不需要参考模块就可以做到这一点。在这种情况下,你实际上不能用这种方式修补“foobar”,但这仅仅是因为修补程序的工作方式。它需要一个指向要替换的引用的完全限定路径。我会继续更新我的答案,并附上一些关于这个的注释。啊,你说得对。修补程序需要点分隔的模块字符串。但是,试试这个:@patch\uuuu name\uuuuu+'.foobar',它可以修补您当前所在模块中的内容。干杯这可能满足了您的特定需求,但并不是对您实际问题的回答\这可能满足了您的特定需求,但并不是对您实际问题的回答\
import unittest
from unittest.mock import patch
import os
from project import foobar

def os_urandom_mock():
    return 'mocked'

def foobar_mock():
    return 'mocked'


class TestProject(unittest.TestCase):
    @patch(__name__ + '.foobar', side_effect=foobar_mock)
    def test_foobar_mocked(self, foobar_mocked):
        self.assertEqual(foobar(), 'mocked')

    @patch(__name__ + '.foobar')
    def test_foobar_mocked_another(self, foobar_mocked):
        foobar_mocked.return_value = 'mocked'
        self.assertEqual(foobar(), 'mocked')

    def test_foobar_mocked_last_try(self):
        with patch(__name__ + '.foobar') as foobar_mocked:
            foobar_mocked.return_value = 'mocked'
            self.assertEqual(foobar(), 'mocked')

unittest.main()
def baz():
    return 'baz'
from asdf import baz

def foobar():
    return baz()
import unittest
from unittest.mock import patch
import os
from project import foobar

def baz_mock():
    return 'mocked'

class TestProject(unittest.TestCase):
    @patch('project.baz', side_effect=baz_mock)
    def test_foobar_mocked(self, foobar_mocked):
        self.assertEqual(foobar(), 'mocked')

    @patch('project.baz')
    def test_foobar_mocked_another(self, baz_mocked):
        foobar_mocked.return_value = 'mocked'
        self.assertEqual(foobar(), 'mocked')

    def test_foobar_mocked_last_try(self):
        with patch('project.baz') as baz_mocked:
            foobar_mocked.return_value = 'mocked'
            self.assertEqual(foobar(), 'mocked')

unittest.main()