模拟 - 如何在调用者上引发异常?

2022-01-08 00:00:00 python mocking unit-testing

问题描述

假设这是代码

def move(*args, **kwargs):   
    try:
        shutil.move(source, destination)
    except Exception as e:
        raise e

在我的tests.py中

and in my tests.py

@patch.object(shutil, 'move')
def test_move_catch_exception(self, mock_rmtree):
    ''' Tests moving a target hits exception. '''
    mock_rmtree.side_effect = Exception('abc')
    self.assertRaises(Exception, move,
                             self.src_f, self.src_f, **self.kwargs)

它是这么说的

  File "unittests.py", line 84, in test_move_catch_exception
    self.src_f, self.src_f, **self.kwargs)
AssertionError: Exception not raised

如果我在 mock_rmtree 上断言它会通过.如何对调用者进行断言(在本例中为函数 move)?

If I assert on mock_rmtree it will pass. How can I assert on the caller (in this case, the function move)?

正如 aquavitae 指出的那样,主要原因是复制粘贴错误,而且我一开始就断言了一个元组.始终断言正确的返回类型...

As aquavitae pointed out, the primary reasons was copy-paste error, and also I was asserting a tuple in the beginning. Always asseert with the right return type...


解决方案

您的示例中有错字,缺少 '.

You've got a typo in your example, missing a '.

不完全清楚你在问什么,但如果我理解正确的话,你问的是如何测试在 move 中捕获了引发的异常.一个问题是您正在修补 shutil.rmtree,而不是 shutil.move,但您不能确定 shutil.rmtree 是否会永远被称为.shutil.move 仅在成功复制目录时才实际调用 shutil.rmtree ,但是由于您将 self.src_f 复制到自身,因此不会发生.虽然这不是一个很好的修补方法,因为 shutil.move 将调用 shutil.rmtree 的假设根本无法保证,并且取决于实现.

Its not entirely clear what you're asking, but if I understand you correctly, you're asking how to test that a raised exception is caught inside move. One problem is that you're patching shutil.rmtree, not shutil.move, but you can't be certain thatshutil.rmtree will ever be called. shutil.move only actually calls shutil.rmtree if it successfully copies a directory, but since you're copying self.src_f to itself, this doesn't happen. This is not a very good way of patching it though, because the assumption that shutil.move will call shutil.rmtree at all is not guaranteed and is implementation dependent.

至于如何测试,简单检查返回值是否符合预期:

As for how to test it, simply check that the return value is as expected:

@patch.object(shutil, 'move')
def test_move_catch_exception(self, mock_move):
    ''' Tests moving a target hits exception. '''
    e = OSError('abc')
    mock_move.side_effect = e
    returns = move(self.src_f, self.src_f, **self.kwargs)
    assert returns == (False, e)

相关文章