模拟 class 属性

Mock class attribute

假设我有一些 class:

class Worker:

_processor: Processor

def set_processor(self, processor: Processor):
    self._processor = processor

def start_work(self, data: bytes):
    self._processor.parse(data)

测试set_processor方法很简单,就这样:

def test_set_processor():
    mock_processor = Mock()
    worker = Worker()
    worker.set_processor(mock_processor)

    assert worker._processor == mock_processor

我们只是将 mock 传递给 set_processor 方法并检查 self._processor 现在是否等于 mock。

但是如何测试 start_work 方法呢?我想确定 self._processor 会被 data 调用吗? 如果我尝试修补 _processor 属性,我会遇到错误。

单元测试解决方案如下:

worker.py:

from typing import Any

Processor = Any


class Worker:
    _processor: Processor

    def set_processor(self, processor: Processor):
        self._processor = processor

    def start_work(self, data: bytes):
        self._processor.parse(data)

test_worker.py:

import unittest
from worker import Worker
from unittest.mock import Mock


class TestWorker(unittest.TestCase):
    def test_set_processor(self):
        mock_processor = Mock()
        worker = Worker()
        worker.set_processor(mock_processor)
        assert worker._processor == mock_processor
        worker.start_work(b'')
        mock_processor.parse.assert_called_once_with(b'')


if __name__ == '__main__':
    unittest.main()

100% 覆盖率的单元测试结果:

.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
(venv) ☁  python-codelab [master] ⚡  coverage report -m                                                                                              
Name                                        Stmts   Miss  Cover   Missing
-------------------------------------------------------------------------
src/Whosebug/59202648/test_worker.py      13      0   100%
src/Whosebug/59202648/worker.py            8      0   100%
-------------------------------------------------------------------------
TOTAL                                          21      0   100%

源代码:https://github.com/mrdulin/python-codelab/tree/master/src/Whosebug/59202648