我是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
答案 0 :(得分:19)
无需提供单独的构造函数。模拟修补代码以用模拟替换对象。只需在测试方法上使用mock.patch()
decorator;它将传递对生成的模拟对象的引用。
在创建实例之前, 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_data
时,mock.patch()
代码将模拟对象替换为producer.Producer
引用。然后,您的MyCoordinator
类使用这些模拟对象而不是真实代码。调用producer.Producer()
返回一个新的模拟对象(mock_producer.return_value
引用的同一对象)等。
我假设producer
和consumer
是顶级模块名称。如果不是,请提供完整的导入路径。来自mock.patch()
文档:
target 应为
'package.module.ClassName'
形式的字符串。导入目标并将指定的对象替换为新对象,因此目标必须可从您正在调用的环境中导入patch()
。执行修饰函数时导入目标,而不是在装饰时导入。