pytest:无法模拟我的班级的 __init__

2024-03-05

我有一个习惯Db类,具有基本操作。我正在尝试围绕它编写测试 - 在__init__在我的班级中,我正在连接到我想避免的实际数据库(因为我只是编写单元测试,不需要连接到实际数据库)。

这是我的代码:

@mock.patch( 'mydb.Db' )
@pytest.mark.parametrize( "input,expected", [
    (
        {
            'key'   : "x" ,
            'value' : 5   ,
        } , 
        [  "x = 5" ]
    ) ,
    ])
def test_where_statement( mock_db, input, expected):
    mock_db.__init__.return_value = None
    assert expected == mock_db.where( input[ "key"] , input[ "value" ] )._condition_list

它在我将 return_value 设置为 None 的行上失败 - 问题是:

    def test_where_statement( mock_db, input, expected):
>       mock_db.__init__.return_value = None
E       AttributeError: 'instancemethod' object has no attribute 'return_value'

我只想模拟 init 函数,然后能够运行 where 函数(例如,它构建我的查询的 where 语句)。

我缺少什么?


AFAIK 你可以在这里有两种不同的方法。一是嘲讽__init__方法直接与您的补丁一起使用,它将按预期工作(原始__init__不会被调用)。

@mock.patch('mydb.Db.__init__', return_value=None)

其次,使用您当前的方法,而不是将 None 值分配给mock_db__init__方法(不会一路调用,因为对象已经是模拟的)将 return_value 分配给mock_db,调用该方法以获取 Db 类的实例(mock_db.return_value应该指向 Db 实例的模拟版本),或者如果您对更改默认模拟的行为不感兴趣,则将其保留为原样,因为代码将被执行(AFAIR 当调用类来创建其实例时某些模拟对象是自动创建的)。

编辑: 您需要确保在正确的位置模拟 mydb。经验法则是模拟事物的导入位置,而不是它们所在的位置。换句话说,如果您想测试放置在文件中的代码my_package.my_module具有import mydb你需要修补my_package.my_module.mydb.Db.

关于模拟的很棒的资源:ELI5 模拟解释 https://www.toptal.com/python/an-introduction-to-mocking-in-python

首先应该注意的事情之一是我们使用mock.patch方法装饰器来模拟位于mymodule.os的对象,并将该模拟注入到我们的测试用例方法中。仅仅模拟 os 本身,而不是在 mymodule.os 中引用它,不是更有意义吗?

嗯,在导入和管理模块方面,Python 有点像一条狡猾的蛇。在运行时, mymodule 模块有自己的操作系统,该操作系统被导入到模块中自己的本地范围中。因此,如果我们模拟 os,我们将不会在 mymodule 模块中看到模拟的效果。 不断重复的口头禅是:

模拟一个物品的使用地,而不是它的来源地。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pytest:无法模拟我的班级的 __init__ 的相关文章

随机推荐