pytest模拟本地对象实例在模拟对象中

发布于 2025-02-04 08:58:41 字数 1846 浏览 3 评论 0原文

问题

模拟并对无法从包含对象访问的本地实例对象进行断言。

最小示例

executor是要模拟的类。

class Executor:    
    def execute(self, func, *args):
        func(*args)

模拟executor

import pytest
@pytest.fixture
def executor(mocker):
    mocker.patch('executor.Executor.execute')
    return Executor()

testing executor.execute立即调用。

def test_execute(executor):
    func = lambda x: x**2
    executor.execute(func, 7)
    Executor.execute.assert_called_once_with(func, 7)

    # this fails -- how to test a situation where one doesn't have access to the lambda
    # func2 = lambda y:y**2
    # Executor.execute.assert_called_once_with(func2, 7)

更普遍地

def test_execute_with_complex_args(executor):
    def somefunc(x, y):
        x.increment(y)
    class SomeObj:
        x=30
        def increment(self, y):
            self.x += y
 
    obj = SomeObj()
    executor.execute(somefunc, obj, 7)
    Executor.execute.assert_called_once()

    # this is assuming we have access to somefunc and obj instances
    Executor.execute.assert_called_once_with(somefunc, obj, 7)

    # how to verify that increment was called with arg 7?
    # somefunc and obj are instances that are not accessible? 

为什么这是重要的/对这种圆形测试的需求是什么?

我正在测试使用sqlalchemy的数据库客户端。我想验证查询是通过正确参数执行的。客户端中的一个典型功能看起来像:

def get_job(self, job_id: UUID) -> Job:
        return run_transaction(sessionmaker(bind=self.engine),
                               lambda s: copy(s.query(Job).filter(Job.id == job_id).one()))

sessionmakerrun_transaction是可模拟的,可以进行测试,但我想验证session.query方法被适当地称为。

Problem

Mock and perform assertions on local instance objects that are not accessible from the encompassing object.

Minimum Example

Executor is the class to be mocked.

class Executor:    
    def execute(self, func, *args):
        func(*args)

Mocking Executor

import pytest
@pytest.fixture
def executor(mocker):
    mocker.patch('executor.Executor.execute')
    return Executor()

Testing Executor.execute is called at once.

def test_execute(executor):
    func = lambda x: x**2
    executor.execute(func, 7)
    Executor.execute.assert_called_once_with(func, 7)

    # this fails -- how to test a situation where one doesn't have access to the lambda
    # func2 = lambda y:y**2
    # Executor.execute.assert_called_once_with(func2, 7)

More generally

def test_execute_with_complex_args(executor):
    def somefunc(x, y):
        x.increment(y)
    class SomeObj:
        x=30
        def increment(self, y):
            self.x += y
 
    obj = SomeObj()
    executor.execute(somefunc, obj, 7)
    Executor.execute.assert_called_once()

    # this is assuming we have access to somefunc and obj instances
    Executor.execute.assert_called_once_with(somefunc, obj, 7)

    # how to verify that increment was called with arg 7?
    # somefunc and obj are instances that are not accessible? 

Why is this important/what is the need for such a round-about testing?

I am testing a database client that uses SqlAlchemy. I want to verify a query is executed with the right arguments. A typical function in the client looks like this:

def get_job(self, job_id: UUID) -> Job:
        return run_transaction(sessionmaker(bind=self.engine),
                               lambda s: copy(s.query(Job).filter(Job.id == job_id).one()))

sessionmaker and run_transaction are mockable and can be tested but I want to verify the Session.query method is called appropriately.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文