簡體   English   中英

我如何模擬部分python構造函數進行測試?

[英]How do I mock part of a python constructor just for testing?

我是Python的新手,所以如果這是一個重復或過於簡單的問題我會道歉。 我編寫了一個協調器類,調用另外兩個使用kafka-python庫來發送/讀取Kafka數據的類。 我想為我的協調員課程編寫一個單元測試,但是我很難弄清楚如何最好地解決這個問題。 我希望我可以創建一個替代構造函數,我可以將我的模擬對象傳遞給,但這似乎不起作用,因為我得到一個錯誤,test_mycoordinator無法解決。 我是否會以錯誤的方式測試這門課程? 我應該測試一種pythonic方式嗎?

這是我的測試類到目前為止的樣子:

import unittest
from mock import Mock
from mypackage import mycoordinator

class MyTest(unittest.TestCase):

    def setUpModule(self):
        # Create a mock producer
        producer_attributes = ['__init__', 'run', 'stop']
        mock_producer = Mock(name='Producer', spec=producer_attributes)

        # Create a mock consumer
        consumer_attributes = ['__init__', 'run', 'stop']
        data_out = [{u'dataObjectID': u'test1'},
                    {u'dataObjectID': u'test2'},
                    {u'dataObjectID': u'test3'}]
        mock_consumer = Mock(
            name='Consumer', spec=consumer_attributes, return_value=data_out)

        self.coor = mycoordinator.test_mycoordinator(mock_producer, mock_consumer)

    def test_send_data(self):
        # Create some data and send it to the producer
        count = 0
        while count < 3:
            count += 1
            testName = 'test' + str(count)
            self.coor.sendData(testName , None)

以下是我要測試的課程:

class MyCoordinator():
    def __init__(self):
        # Process Command Line Arguments using argparse  
        ...

        # Initialize the producer and the consumer
        self.myproducer = producer.Producer(self.servers,
                                            self.producer_topic_name)

        self.myconsumer = consumer.Consumer(self.servers,
                                            self.consumer_topic_name)

    # Constructor used for testing -- DOES NOT WORK
    @classmethod
    def test_mycoordinator(cls, mock_producer, mock_consumer):
        cls.myproducer = mock_producer
        cls.myconsumer = mock_consumer

    # Send the data to the producer
    def sendData(self, data, key):
        self.myproducer.run(data, key)

    # Receive data from the consumer
    def getData(self):
        data = self.myconsumer.run()
        return data

不需要提供單獨的構造函數。 模擬修補代碼以用模擬替換對象。 只需在測試方法上使用mock.patch()裝飾器 ; 它將傳遞對生成的模擬對象的引用。

創建實例之前 ,然后模擬出producer.Producer()consumer.Consumer()

import mock

class MyTest(unittest.TestCase):
    @mock.patch('producer.Producer', autospec=True)
    @mock.patch('consumer.Consumer', autospec=True)
    def test_send_data(self, mock_consumer, mock_producer):
        # configure the consumer instance run method
        consumer_instance = mock_consumer.return_value
        consumer_instance.run.return_value = [
            {u'dataObjectID': u'test1'},
            {u'dataObjectID': u'test2'},
            {u'dataObjectID': u'test3'}]

        coor = MyCoordinator()
        # Create some data and send it to the producer
        for count in range(3):
            coor.sendData('test{}'.format(count) , None)

        # Now verify that the mocks have been called correctly
        mock_producer.assert_has_calls([
            mock.Call('test1', None),
            mock.Call('test2', None),
            mock.Call('test3', None)])

所以當test_send_datamock.patch()代碼用mock對象替換producer.Producer引用。 然后,您的MyCoordinator類使用這些模擬對象而不是真實代碼。 調用producer.Producer()返回一個新的模擬對象(與mock_producer.return_value引用的對象相同)等。

我假設producerconsumer是頂級模塊名稱。 如果不是,請提供完整的導入路徑。 mock.patch()文檔:

target應該是'package.module.ClassName'形式的字符串。 導入目標並將指定的對象替換為新對象,因此目標必須可從您調用patch()的環境中導入。 執行修飾函數時導入目標,而不是在裝飾時導入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM