简体   繁体   English

使用模拟和修补外部模块的Python单元测试

[英]Python Unit testing with mock and patch a foreign modul

I would like to test a class which uses the Serial class from serial modul. 我想测试一个使用来自串行模块的Serial类的类。 I know i have to mock them, but i don't get it up and running: 我知道我必须模拟它们,但是我没有启动它并运行它:

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)
  • For the complete TestClass: How do i mock the Serial class so that it won't use the real one? 对于完整的TestClass:我如何模拟Serial类,以便它不使用真正的类?

  • For some tests: How do i mock the Serial.read(x) with parameter x and return value? 对于某些测试:如何使用参数x模拟Serial.read(x)并返回值? (just like Serial.inWaiting()) (就像Serial.inWaiting()一样)

  • For some tests: How do i mock the Serial.write(message) with parameter and then test it for calling with parameter message? 对于某些测试:如何模拟带有参数的Serial.write(message),然后测试其是否带有参数message进行调用?

  • One bonus question: should i use unittest2 ? 一个奖励问题:我应该使用unittest2吗?

Maybe the best way to do it is to patch Serial class. 也许最好的方法是patch Serial类。 In your case you imported Serial in test module and to patch it you should use something like this 在您的情况下,您在测试模块中导入了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()

Your test should work if you change any reference to mock by self.mock and test_read as follow : 如果您通过self.mocktest_read mock的任何引用更改为以下self.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)

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

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