Python 使用 mock 和 patch 外部模块进行单元测试
Python Unit testing with mock and patch a foreign modul
我想测试一个 class,它使用来自串行模块的串行 class。
我知道我必须嘲笑他们,但我不明白 运行:
from serial import Serial
import unittest
from mock import patch, MagicMock
class MyClass(object):
def __init__(self):
self.ser = Serial('/dev', 123)
def write(self, message):
if self.ser:
self.ser.write(message)
return True
def read(self):
if self.ser.inWaiting():
return self.ser.read(1)
return None
class MyClassTest(unittest.TestCase):
def setUp(self):
self.mc = MyClass()
def test_init(self):
self.mc = MyClass()
#Check if...
mock.assert_called_with('/dev', 123)
def test_write(self):
self.mc.write('lala')
#Check if...
mock.write.assert_called_with('lala')
def test_read(self):
#patch inWaiting function...
mock.inWaiting.retval = 4
#patch inWaiting function...
mock.read.retval = 'lulu'
x = self.mc.read()
self.assertEqual('lulu')
#Check if...
mock.read.assert_called_with(1)
对于完整的 TestClass:我如何模拟串行 class 以便它不会使用真实的?
对于某些测试:如何使用参数 x 和 return 值模拟 Serial.read(x)? (就像 Serial.inWaiting())
对于某些测试:如何使用参数模拟 Serial.write(message),然后测试它是否可以使用参数 message 调用?
一个奖励问题:我应该使用 unittest2 吗?
也许最好的方法是 patch
Serial
class。在您的情况下,您在测试模块中导入了 Serial
并对其进行了修补,您应该使用类似这样的东西
def setUp(self):
patcher = patch("__main__.Serial", autospec=True)
self.mock = patcher.start()
self.addCleanup(patcher.stop)
self.mc = MyClass()
self.mock.reset_mock()
如果您通过 self.mock
和 test_read
更改对 mock
的任何引用,则您的测试应该有效,如下所示:
def test_read(self):
self.mock.inWaiting.return_value = 4
self.mock.read.return_value = 'lulu'
self.assertEqual(self.mc.read(), 'lulu')
self.mock.read.assert_called_with(1)
我想测试一个 class,它使用来自串行模块的串行 class。 我知道我必须嘲笑他们,但我不明白 运行:
from serial import Serial
import unittest
from mock import patch, MagicMock
class MyClass(object):
def __init__(self):
self.ser = Serial('/dev', 123)
def write(self, message):
if self.ser:
self.ser.write(message)
return True
def read(self):
if self.ser.inWaiting():
return self.ser.read(1)
return None
class MyClassTest(unittest.TestCase):
def setUp(self):
self.mc = MyClass()
def test_init(self):
self.mc = MyClass()
#Check if...
mock.assert_called_with('/dev', 123)
def test_write(self):
self.mc.write('lala')
#Check if...
mock.write.assert_called_with('lala')
def test_read(self):
#patch inWaiting function...
mock.inWaiting.retval = 4
#patch inWaiting function...
mock.read.retval = 'lulu'
x = self.mc.read()
self.assertEqual('lulu')
#Check if...
mock.read.assert_called_with(1)
对于完整的 TestClass:我如何模拟串行 class 以便它不会使用真实的?
对于某些测试:如何使用参数 x 和 return 值模拟 Serial.read(x)? (就像 Serial.inWaiting())
对于某些测试:如何使用参数模拟 Serial.write(message),然后测试它是否可以使用参数 message 调用?
一个奖励问题:我应该使用 unittest2 吗?
也许最好的方法是 patch
Serial
class。在您的情况下,您在测试模块中导入了 Serial
并对其进行了修补,您应该使用类似这样的东西
def setUp(self):
patcher = patch("__main__.Serial", autospec=True)
self.mock = patcher.start()
self.addCleanup(patcher.stop)
self.mc = MyClass()
self.mock.reset_mock()
如果您通过 self.mock
和 test_read
更改对 mock
的任何引用,则您的测试应该有效,如下所示:
def test_read(self):
self.mock.inWaiting.return_value = 4
self.mock.read.return_value = 'lulu'
self.assertEqual(self.mc.read(), 'lulu')
self.mock.read.assert_called_with(1)