pytest - 修补类不起作用,而是调用类

不知道为什么,但这是我的代码片段:


stats_collector.py


class StatsCollector( object ) :

def __init__( self, user_id, app_id ) :

    logging.info( "Stats: APP_ID = {0}, ID = {1}".format( app_id, user_id ) )

mydb.py


from namespacename.mylibname.stats_collector import StatsCollector

class Db( object ) :

    # constructor/destructor

    def __init__( self, dbname ) :

        ....


    def beginTransaction( self, user_id, app_id ) :

        logging.info( "Begin" )

        self._stats = StatsCollector( user_id, app_id ) 

test_mylibname_mydb


from namespacename.mylibname.mydb import Db

from namespacename.mylibname.stats_collector import StatsCollector

@pytest.mark.mydb_temp

@mock.patch( 'namespacename.mylibname.stats_collector.StatsCollector')

def test_db_beginTransaction( mock_stats_collector ) :

    db = Db( TEST_DB_NAME )

    mock_stats_collector.return_value = mock.Mock()

    db.beginTransaction( TEST_ID, TEST_APP_ID )

    ......

    ......

我可以在我的登录中看到我的stats_collector.__init__- 为什么我要输入它?不应该在我的内部beginTransaction调用StatsCollector返回值是 MockObject 并且我不应该看到任何日志吗?


结构如下:


tests/

├── mylibname

│   ├── test_mylibname_mydb.py

namespacename/mylibname

├── stats_collector

│   ├── mylibname_stats_collector.py

│   ├── __init__.py

├── mydb

│   ├── mylibname_mydb.py

│   ├── __init__.py

** 编辑 **


遵循有关评论的建议 -


@mock.patch( 'namespacename.mylibname.mydb.StatsCollector')

def test_db_beginTransaction( mock_stats_init ) :

    db = Db( TEST_DB_NAME )

    db.beginTransaction( TEST_UUID, TEST_APP_ID )

    print db._transaction

    assert db._transaction is mock_stats_init

让我:


E       AssertionError: assert <namespacename.mylibname.stats_collector.mylibname_stats_collector.StatsCollector object at 0x7f42d837b110> is <MagicMock name='StatsCollector' id='139925072008976'>

E        +  where <namespacename.mylibname.stats_collector.mylibname_stats_collector.StatsCollector object at 0x7f42d837b110> = <namespacename.mylibname.mydb.mylibname_mydb.Db object at 0x7f42d8365850>._transaction



绝地无双
浏览 187回答 3
3回答

MYYA

您需要修补正在测试的模块中的符号“A”,即“B”。当你这样做时@mock.patch("full.path.A"),它应该是:@mock.patch("full.path.to.B.A")现在A模块中的符号B用你的模拟打了补丁。

米琪卡哇伊

你不是错过了文件本身的名称吗?@mock.patch(&nbsp;'namespacename.mylibname.stats_collector.mylibname_stats_collector.StatsCollector')

小怪兽爱吃肉

当我写这篇文章时,你可能已经想通了。经验法则:不要在定义类或函数的地方打补丁,而是在使用它们的地方打补丁。a.pyclass A:&nbsp; &nbsp; def exponent(self, a, b)&nbsp; &nbsp; &nbsp; &nbsp; return a ** b&nbsp; &nbsp;&nbsp;b.py&nbsp; &nbsp;&nbsp;from a import Aclass B:&nbsp; &nbsp;def add_constat(a, b, c)&nbsp; &nbsp; &nbsp; return A().exponent(a, b) + c&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了测试 add_constant 方法,您可能会想像这样修补 ATestB:@patch('a.A.exponent', mock_a)&nbsp; &nbsp; test_add_constant(self, mock_a)&nbsp;这是错误的,因为您正在修补给出定义的文件中的类。A 在类 B 的文件 b 中使用。因此,您应该修补该类。TestB:&nbsp; &nbsp; @patch('b.A')&nbsp; &nbsp; test_add_constant(self, mock_a):&nbsp; &nbsp; # mock_a is fake class of A, the return_value of mock_a gives us an instance (object) of the class(A)&nbsp; &nbsp; instance_a = mock_a.return_value #&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; # we now have instance of the class i.e A, hence it is possible to call the methods of class A&nbsp; &nbsp;&nbsp; &nbsp; instance_a.exponent.return_value = 16&nbsp; &nbsp;&nbsp; &nbsp; assert 26 = B().add_constant(2,4,10)我对您的代码进行了一些修改,以便它可以在我的 Python 环境中使用。stats_collector.pyclass StatsCollector:&nbsp; &nbsp; def __init__(self, user_id, app_id):&nbsp; &nbsp; &nbsp; &nbsp; self.user_id = user_id&nbsp; &nbsp; &nbsp; &nbsp; self.app_id = app_id&nbsp; &nbsp; def stat(self):&nbsp; &nbsp; &nbsp; &nbsp; return self.user_id + ':' + self.app_idmydb.pyfrom stats_collector import StatsCollectorimport loggingclass Db:&nbsp; &nbsp; # constructor&nbsp; &nbsp; def __init__(self, db_name):&nbsp; &nbsp; &nbsp; &nbsp; self.db_name = db_name&nbsp; &nbsp; def begin_transaction(self, user_id, app_id):&nbsp; &nbsp; &nbsp; &nbsp; logging.info("Begin")&nbsp; &nbsp; &nbsp; &nbsp; stat = StatsCollector(user_id, app_id).stat()&nbsp; &nbsp; &nbsp; &nbsp; if stat:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return user_id + ':' + app_id&nbsp; &nbsp; &nbsp; &nbsp; return "wrong User"使用类似的比喻:为了测试文件 mydb.py 的 Db 类中的“begin_transaction”,您需要修补 mydb.py 文件中使用的 StatsCollector 类test_mydb.pyfrom unittest.mock import patchfrom unittest import TestCaseclass TestDb(TestCase):&nbsp; &nbsp; @patch('mydb.StatsCollector')&nbsp; &nbsp; def test_begin_transaction(self, db_class_mock):&nbsp; &nbsp; &nbsp; &nbsp; # db_class_mock is the mock of the class, it is not an instance of the DB class.&nbsp; &nbsp; &nbsp; &nbsp; # to create an instance of the class, you need to call return_value&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; db_instance = db_class_mock.return_value&nbsp; &nbsp; &nbsp; &nbsp; db_instance.stat.return_value = 1&nbsp; &nbsp; &nbsp; &nbsp; # i prefere to do the above two lines in just one line as&nbsp; &nbsp; &nbsp; &nbsp; #db_class_mock.return_value.stat.return_value = 1&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; db = Db('stat')&nbsp; &nbsp; &nbsp; &nbsp; expected = db.begin_transaction('Addis', 'Abeba')&nbsp; &nbsp; &nbsp; &nbsp; assert expected == 'Addis' + ':' + 'Abeba'&nbsp; &nbsp; &nbsp; &nbsp; # set the return value of stat method&nbsp; &nbsp; &nbsp; &nbsp; db_class_mock.return_value.stat.return_value = 0&nbsp; &nbsp; &nbsp; &nbsp; expected = db.begin_transaction('Addis', 'Abeba')&nbsp; &nbsp; &nbsp; &nbsp; assert expected == "wrong User"我希望这可以帮助网络中的某人
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python