简体   繁体   English

Mocking class 属性是从另一个模块单元测试 python 导入的 class

[英]Mocking class attribute that is a class imported from another module unittest python

I have following project structure:我有以下项目结构:

├───pa
│   |───__init__.py
|   |─── a1.py
|   |─── test_a1.py
|
├───pb
│   |───__init__.py
|   |─── b1.py

With following code: b1.py:使用以下代码:b1.py:

class B1:

    def __init__(self):
        self.text = "Unmocked_B1"

    def get_text(self):
        return self.text

pb.__init__.py: pb.__init__.py:

from .b1 import B1

a1.py: a1.py:

from src.pb import B1


class A1:

    def __init__(self):
        self.b = B1()

    def get_text(self):
        return self.b.get_text()

pa.__init__.py: pa.__init__.py:

from .a1 import A1

And I want to mock self.b in class A1 using unittest.mock.patch in such way that following code in test_a1.py will print "Mocked B1"我想在 class A1 中使用 unittest.mock.patch 模拟 self.b,这样 test_a1.py 中的以下代码将打印“模拟 B1”

test_a1.py: test_a1.py:

from unittest import TestCase
from unittest.mock import patch, PropertyMock
from . import A1


class TestB1(TestCase):

    @patch('Some args')
    def test_get_text(self, mocked_b1):
        # Some code
        
        a1 = A1()
        print(a1.get_text())  # Should print: Mocked B1

I tried both mocking B1 import with:我尝试了 mocking B1 导入:

@patch('src.pb.b1.B1')
    def test_get_text(self, mocked_b1):
        mocked_b1.get_text.return_value = 'Mocked B1'

        a1 = A1()
        print(a1.get_text())  # Should print: Mocked B1

And mocking property of a1 with property mock:和 a1 的 mocking 属性与属性模拟:

@patch('pa.a1.A1.b', new_callable=PropertyMock)
    def test_get_text(self, mocked_b):
        mocked_b.get_text.return_value = 'Mocked B1'

        a1 = A1()
        print(a1.get_text())  # Should print: Mocked B1

Which does not seem to work even when I make attribute b inside A1 static instead of dynamic.即使我在 A1 static 中创建属性 b 而不是动态的,这似乎也不起作用。

Is there a way to mock this attribute?有没有办法模拟这个属性? It would be perfect if it would work on dynamic attribute as shown earlier.如果它能像前面所示的那样对动态属性起作用,那就太完美了。

I'm using python 3.10我正在使用 python 3.10

Try the following syntax that uses patch.object and context manager (instruction with ):尝试以下使用patch.object和上下文管理器的语法( with指令):

class TestB1(TestCase):
    def test_get_text(self):
        a1 = A1()
        with patch.object(a1, "b") as mocked_b1:
            mocked_b1.get_text.return_value = 'Mocked B1'

            print(a1.get_text())  # Prints: Mocked B1

Thank you frankfalse for answer of course similar solution with patch decorator also works (I discovered it this morning):谢谢 frankfalse 的回答,当然类似的补丁装饰器解决方案也有效(我今天早上发现了它):

@patch('src.pa.a1.B1')
def test_get_text(self, mocked_B1):
    instance = mocked_B1.return_value
    instance.get_text.return_value = 'Mocked B1'

    a1 = A1()
    print(a1.get_text())  # Prints: Mocked B1

Don't know if there is solution with property mock不知道有没有property mock的解决方案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM