繁体   English   中英

Mocking 带有单元测试补丁的两个函数

[英]Mocking two functions with patch for a unit test

我有一个 function 我想单元测试包含调用另外两个函数。 我不确定如何使用补丁同时正确地模拟这两个功能。 我在下面提供了一个例子来说明我的意思。 当我运行 nosetests 时,测试通过了,但我觉得必须有一种更简洁的方法来做到这一点,我并不真正理解关于 f.close() 的文章......

目录结构如下所示:

program/
  program/
    data.py
  tests/
    data_test.py

数据.py:

import cPickle

def write_out(file_path, data):
    f = open(file_path, 'wb')
    cPickle.dump(data, f)
    f.close()

数据测试.py:

from mock import MagicMock, patch

def test_write_out():
    path = '~/collection'
    mock_open = MagicMock()
    mock_pickle = MagicMock()
    f_mock = MagicMock()
    with patch('__builtin__.open', mock_open):
        f = mock_open.return_value
        f.method.return_value = path
        with patch('cPickle.dump', mock_pickle):
            write_out(path, 'data')
            mock_open.assert_called_once_with('~/collection', 'wb')
            f.close.assert_any_call()
            mock_pickle.assert_called_once_with('data', f)

结果:

$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.008s
OK

您可以使用修补程序装饰器简化测试并将其嵌套(默认情况下它们是MagicMock对象):

@patch('cPickle.dump')
@patch('__builtin__.open')
def test_write_out(mock_open, mock_pickle):
    path = '~/collection'
    f = mock_open.return_value
    f.method.return_value = path

    write_out(path, 'data')

    mock_open.assert_called_once_with('~/collection', 'wb')
    mock_pickle.assert_called_once_with('data', f)
    f.close.assert_any_call()

MagicMock实例的调用返回一个新的MagicMock实例,因此您可以检查返回的值是否像任何其他模拟对象一样被调用。 在这种情况下, f是名为'open()'MagicMock (尝试打印f )。

除了响应@Matti John之外,您还可以在函数test_write_out使用patch

from mock import MagicMock, patch

def test_write_out():
    path = '~/collection'
    with patch('__builtin__.open') as mock_open, \
            patch('cPickle.dump') as mock_pickle:

        f = mock_open.return_value
        ...

从 Python 3.10 开始,您可以像这样使用带括号的上下文管理

from unittest.mock import patch


def test_write_out():
    with (
        patch('cPickle.dump'),
        patch('__builtin__.open') as open_mock,  # example of using `as`
    ):
        yield

这是一个关于如何使用mock在create_collection函数中测试引发ConflictError的简单示例:

import os
from unittest import TestCase
from mock import patch
from ..program.data import ConflictError, create_collection


class TestCreateCollection(TestCase):
    def test_path_exists(self):
        with patch.object(os.path, 'exists') as mock_method:
            mock_method.return_value = True

            self.assertRaises(ConflictError, create_collection, 'test')

请参阅模拟文档和Michael Foord 对模拟的精彩介绍

暂无
暂无

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

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