标签: python-mock

你如何模拟修补python类并为每个实例化获取一个新的Mock对象?

好的,
我知道这在手册中有提及,可能side_effect与/和/有关return_value,但一个简单直接的例子对我帮助很大.

我有:

class ClassToPatch():
   def __init__(self, *args):
       _do_some_init_stuff()

   def some_func():
       _do_stuff()


class UUT():
    def __init__(self, *args)
       resource_1 = ClassToPatch()
       resource_2 = ClassToPatch()
Run Code Online (Sandbox Code Playgroud)

现在,我想对这个UUT类进行单元测试,然后嘲笑ClassToPatch.知道UUT该类将实例化两个ClassToPatch对象,我希望Mock框架为每个实例化返回一个新的Mock对象,所以我可以稍后在每个实例上断言.

如何@patch在测试用例中使用装饰器实现此目的?即,如何修复以下代码示例?

class TestCase1(unittest.TestCase):

    @patch('classToPatch.ClassToPatch',autospec=True)
    def test_1(self,mock1,mock2):
        _assert_stuff()
Run Code Online (Sandbox Code Playgroud)

python mocking python-mock python-unittest

26
推荐指数
1
解决办法
2万
查看次数

如何使用临时文件系统在python中模拟os.walk?

我正在尝试测试一些使用os.walk的代码.我想创建一个临时的内存文件系统,我可以填充样本(空)文件和os.walk将返回的目录.这样可以省去模拟os.walk调用以模拟递归的复杂性.

具体来说,我要测试的代码是:

if recursive:
    log.debug("Recursively searching for files under %s" % path)

    for (dir_path, dirs, files) in os.walk(path):
        log.debug("Found %d files in %s: %s" % (len(files), path, files))
        for f in [os.path.join(dir_path, f) for f in files
                  if not re.search(exclude, f)]:
            yield f
else:
    log.debug("Non-recursively searching for files under %s" % path)

    for (dir_path, dirs, files) in os.walk(path):
        log.debug("Found %d files in %s: %s" % (len(files), path, files))
        for f in [os.path.join(dir_path, f) for f in files
                    if not re.search(exclude, …
Run Code Online (Sandbox Code Playgroud)

python testing unit-testing mocking python-mock

26
推荐指数
1
解决办法
6400
查看次数

无法捕获模拟异常,因为它不继承BaseException

我正在开发一个涉及连接到远程服务器,等待响应,然后根据该响应执行操作的项目.我们捕获了几个不同的异常,并且根据捕获的异常而表现不同.例如:

def myMethod(address, timeout=20):
    try:
        response = requests.head(address, timeout=timeout)
    except requests.exceptions.Timeout:
        # do something special
    except requests.exceptions.ConnectionError:
        # do something special
    except requests.exceptions.HTTPError:
        # do something special
    else:
        if response.status_code != requests.codes.ok:
            # do something special
        return successfulConnection.SUCCESS
Run Code Online (Sandbox Code Playgroud)

为了测试这个,我们编写了如下测试

class TestMyMethod(unittest.TestCase):

    def test_good_connection(self):
        config = {
            'head.return_value': type('MockResponse', (), {'status_code': requests.codes.ok}),
            'codes.ok': requests.codes.ok
        }
        with mock.patch('path.to.my.package.requests', **config):
            self.assertEqual(
                mypackage.myMethod('some_address',
                mypackage.successfulConnection.SUCCESS
            )

    def test_bad_connection(self):
        config = {
            'head.side_effect': requests.exceptions.ConnectionError,
            'requests.exceptions.ConnectionError': requests.exceptions.ConnectionError
        }
        with mock.patch('path.to.my.package.requests', **config):
            self.assertEqual(
                mypackage.myMethod('some_address',
                mypackage.successfulConnection.FAILURE
            )
Run Code Online (Sandbox Code Playgroud)

如果我直接运行该函数,一切都按预期发生.我甚raise …

python exception-handling python-mock python-3.3 python-requests

26
推荐指数
2
解决办法
2万
查看次数

在对象上只模拟一个方法

我熟悉其他语言中的其他模拟库,例如Java中的Mockito,但Python的mock库让我的生活混乱.

我有以下课程,我想测试.

class MyClassUnderTest(object):

    def submethod(self, *args):
       do_dangerous_things()

    def main_method(self):
       self.submethod("Nothing.")
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我想确保submethodmain_method执行时调用它,并使用正确的参数调用它.我不想submethod跑,因为它做危险的事情.

我完全不确定如何开始这个.Mock的文档非常难以理解,我不确定甚至可以模拟甚至如何模拟它.

如何submethodmain_method单独保留功能的同时模拟功能?

python mocking python-mock

25
推荐指数
1
解决办法
8200
查看次数

Django测试 - 在所有测试中修补对象

我需要MockMixin为我的测试创建一些.它应该包括调用外部源的所有内容的模拟.例如,每次我在管理面板中保存模型时,我都会调用一些远程URL.如果嘲笑并使用那样的话会很好:

class ExampleTestCase(MockedTestCase):
    # tests
Run Code Online (Sandbox Code Playgroud)

因此,每次我在管理员中保存模型时,例如在功能测试中,应用此模拟而不是调用远程URL.

这有可能吗?我能够为1个特定测试做到这一点,这不是问题.但是有一些全局模拟更有用,因为我经常使用它.

python django unit-testing django-testing python-mock

25
推荐指数
3
解决办法
1万
查看次数

在Python中使用/ import语句进行模拟修补

我试图让mock.patch处理以下示例代码:

from mock import patch
from collections import defaultdict

with patch('collections.defaultdict'):
  d = defaultdict()
  print 'd:', d
Run Code Online (Sandbox Code Playgroud)

这输出如下:

d: defaultdict(None, {})
Run Code Online (Sandbox Code Playgroud)

这意味着defaultdict没有修补.

如果我用直接导入语句替换from/import语句,它可以工作:

from mock import patch
import collections

with patch('collections.defaultdict'):
 d = collections.defaultdict()
 print 'd:', d
Run Code Online (Sandbox Code Playgroud)

输出是:

d: <MagicMock name='defaultdict()' id='139953944084176'>
Run Code Online (Sandbox Code Playgroud)

有没有办法使用from/import修补呼叫?

谢谢

python python-mock

24
推荐指数
2
解决办法
2万
查看次数

自定义unittest.mock.mock_open进行迭代

我应该如何自定义unittest.mock.mock_open来处理这段代码?

file: impexpdemo.py
def import_register(register_fn):
    with open(register_fn) as f:
        return [line for line in f]
Run Code Online (Sandbox Code Playgroud)

我第一次尝试尝试read_data.

class TestByteOrderMark1(unittest.TestCase):
    REGISTER_FN = 'test_dummy_path'
    TEST_TEXT = ['test text 1\n', 'test text 2\n']

    def test_byte_order_mark_absent(self):
        m = unittest.mock.mock_open(read_data=self.TEST_TEXT)
        with unittest.mock.patch('builtins.open', m):
            result = impexpdemo.import_register(self.REGISTER_FN)
            self.assertEqual(result, self.TEST_TEXT)
Run Code Online (Sandbox Code Playgroud)

这失败了,大概是因为代码不使用read,readline或readlines.unittest.mock.mock_open 的文档说:"read_data是要返回的文件句柄的read(),readline()和readlines()方法的字符串.对这些方法的调用将从read_data中获取数据,直到它耗尽为止这些方法的模拟非常简单.如果你需要更多地控制你要测试代码的数据,你需要自己定制这个模拟.默认情况下,read_data是一个空字符串."

由于文件没有给出暗示上会需要什么样定制我试图return_valueside_effect.都没有奏效.

class TestByteOrderMark2(unittest.TestCase):
    REGISTER_FN = 'test_dummy_path'
    TEST_TEXT = ['test text 1\n', 'test text 2\n']

    def test_byte_order_mark_absent(self):
        m = unittest.mock.mock_open()
        m().side_effect = self.TEST_TEXT
        with unittest.mock.patch('builtins.open', m):
            result = impexpdemo.import_register(self.REGISTER_FN) …
Run Code Online (Sandbox Code Playgroud)

python iteration unit-testing mocking python-mock

24
推荐指数
2
解决办法
7470
查看次数

在python单元测试中模拟类属性的更好方法

我有一个基类,它定义了一个类属性和一些依赖它的子类,例如

class Base(object):
    assignment = dict(a=1, b=2, c=3)
Run Code Online (Sandbox Code Playgroud)

我想用不同的任务对这个类进行单元测试,例如空字典,单项等.当然,这非常简化,不是重构我的类或测试的问题.

我得到的(pytest)测试,最终,工作是

from .base import Base

def test_empty(self):
    with mock.patch("base.Base.assignment") as a:
        a.__get__ = mock.Mock(return_value={})
        assert len(Base().assignment.values()) == 0

def test_single(self):
    with mock.patch("base.Base.assignment") as a:
        a.__get__ = mock.Mock(return_value={'a':1})
        assert len(Base().assignment.values()) == 1
Run Code Online (Sandbox Code Playgroud)

这感觉相当复杂和hacky - 我甚至不完全理解为什么它工作(虽然我熟悉描述符).mock会自动将类属性转换为描述符吗?

一种感觉更符合逻辑的解决方案不起作用:

def test_single(self):
    with mock.patch("base.Base") as a:
        a.assignment = mock.PropertyMock(return_value={'a':1})
        assert len(Base().assignment.values()) == 1
Run Code Online (Sandbox Code Playgroud)

要不就

def test_single(self):
    with mock.patch("base.Base") as a:
        a.assignment = {'a':1}
        assert len(Base().assignment.values()) == 1
Run Code Online (Sandbox Code Playgroud)

我尝试过的其他变种也不起作用(测试中的作业保持不变).

模拟类属性的正确方法是什么?有没有比上面更好/更容易理解的方式?

python unit-testing mocking python-mock

22
推荐指数
5
解决办法
3万
查看次数

修补函数的__call__

我需要在测试中修补当前的日期时间.我正在使用这个解决方案:

def _utcnow():
    return datetime.datetime.utcnow()


def utcnow():
    """A proxy which can be patched in tests.
    """
    # another level of indirection, because some modules import utcnow
    return _utcnow()
Run Code Online (Sandbox Code Playgroud)

然后在我的测试中我做了类似的事情:

    with mock.patch('***.utils._utcnow', return_value=***):
        ...
Run Code Online (Sandbox Code Playgroud)

但今天我想到了一个想法,我可以通过修补__call__功能utcnow而不是额外的功能来简化实现_utcnow.

这对我不起作用:

    from ***.utils import utcnow
    with mock.patch.object(utcnow, '__call__', return_value=***):
        ...
Run Code Online (Sandbox Code Playgroud)

如何优雅地做到这一点?

python time mocking python-mock

21
推荐指数
2
解决办法
2559
查看次数

模拟default = timezone.now进行单元测试

我正在尝试为执行大量日期操作的django应用程序编写单元测试.我为我的测试安装了模拟猴子补丁django的timezone.now.

虽然我能够成功地嘲笑timezone.now时,它通常被称为(实际调用timezone.now()在我的代码,我不能嘲笑它为与一个创建的模型DateTimeFielddefault=timezone.now.


我有一个User包含以下内容的模型:

from django.utils import timezone
...
timestamp = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(default=timezone.now)
...
def save(self, *args, **kwargs):
    if kwargs.pop('modified', True):
        self.modified = timezone.now()
    super(User, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

我的单元测试看起来像这样:

from django.utils import timezone

def test_created(self):
    dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
    with patch.object(timezone, 'now', return_value=dt):
        user = User.objects.create(username='test')
        self.assertEquals(user.modified, dt)
        self.assertEquals(user.timestamp, dt)
Run Code Online (Sandbox Code Playgroud)

assertEquals(user.modified, dt)通过,但assertEquals(user.timestamp, dt)没有.

我怎么能模仿timezone.now,即使default=timezone.now在我的模型中也会创建模拟时间?


编辑

我知道我可以改变我的单元测试以通过timestamp …

python django unit-testing mocking python-mock

17
推荐指数
3
解决办法
5989
查看次数