在nose2中使用mock.patch装饰器

4 投票
1 回答
817 浏览
提问于 2025-04-18 12:27

Nose2 有一个很棒的 Such DSL,它的工作方式类似于 RSpec。之前我直接使用单元测试,并用类似 mock.patch 的方式装饰函数。我想知道,使用 should 装饰的函数和普通的单元测试函数有什么不同,以及我如何能像使用单元测试函数那样使用其他装饰器。

我可以这样让它工作,但似乎失去了 在参数中传递单元测试实例的能力。任何建议都非常感谢。谢谢!

@it.should('do something')
@mock.patch('my.package.lib.b')                                                                
@mock.patch('my.package.lib.a')                                                                   
def test(a, b):
    pass

1 个回答

1

我们知道,装饰器的顺序很重要,所以这些写法都不行:

@it.should('do something')
@mock.patch('datetime.date')
@mock.patch('datetime.time')
def test_1(date, time, case):
    pass

@mock.patch('datetime.time')
@mock.patch('datetime.date')
@it.should('do something')
def test_2(case, date, time):
    pass

这是因为patchshould的实现方式。两个库都对最终装饰后的函数有一些假设,所以不能直接把一个装饰器的结果传给另一个。

不过,我们可以通过外部使用一个“适配器”装饰器来解决这个问题:

import mock
import nose2.tools

def fix_case(f):
    def test(case):
        f(case=case)
    return test

with nose2.tools.such.A('system') as it:

    @it.should('do something')
    @fix_case
    @mock.patch('datetime.time')
    @mock.patch('datetime.date')
    def test_3(date, time, case=None):
        print(date, time, case)

it.createTests(globals())

现在这样就可以用了,结果是:

$ nose2 -v
test 0000: should do something (tests.test_nose2_such.A system) ...
(<MagicMock name='date' id='4334752592'>, <MagicMock name='time' id='4334762000'>,
<tests.test_nose2_such.A system testMethod=test 0000: should do something>)
ok

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

OK

这个方法虽然有点粗糙,但能完成任务。我会看看能否进一步改进,让它更好。

撰写回答