【问题标题】:The pytest test always return abc.is_online Truepytest 测试总是返回 abc.is_online True
【发布时间】:2021-10-13 03:32:24
【问题描述】:

测试总是返回 abc.is_online True。但 abc.is_online 应该为 False,因为 celery 任务在 60 秒后使 is_online 为 False。 错误消息:断言 True == False 其中 True = .is_online

@app.task(name="task.abc_last_active") #Celery task
def abc_last_active():
    now = timezone.localtime()

    for xyz in ABC.objects.all():
        if not xyz.last_active:
            continue

        elapsed = now - xyz.last_active

        if elapsed.total_seconds() >= settings.ABC_TIMEOUT: #60 Sec
            xyz.is_online = False
            xyz.save()

@pytest.fixture
def create_abc():
    abc = ABC.objects.create(
        phone="123234432",
        location=Point(1, 4),
        last_active=timezone.localtime() - timezone.timedelta(seconds=162),
        is_online=True,
    )
    return abc

@pytest.mark.django_db
def test_inactive_abc_gets_deactivated(create_abc):
    print(create_abc.is_online, "before deactivation")

    abc_last_active()

    print(create_abc.is_online, "after deactivation")
    assert create_abc.is_online == False

【问题讨论】:

    标签: django unit-testing django-rest-framework pytest pytest-django


    【解决方案1】:

    在运行 Celery 任务后使用create_abc.refresh_from_db()。每次更改 obj 时,Django 都不会到处访问数据库。

    编辑:改进答案以澄清这里发生了什么。

    您在此处在内存中创建一个新对象(现在保存到数据库中):

    def create_abc():
        ...
    

    然后一个 celery 任务获取 DB 对象 并在内存中创建 一个新对象(测试闭包中的旧对象 create_abc 到那时仍然是旧对象)。 任务完成后,内存中的fixture对象对DB中的新对象一无所知。因此,您必须通过调用 refresh_from_db() 将新的数据库实例加载到旧 obj 中。

    对于测试,我建议不要刷新(因为您可能会忘记刷新)创建显式使用新实例的断言并养成这样的习惯以避免将来出现问题。即:

    @pytest.mark.django_db
    def test_inactive_abc_gets_deactivated(create_abc):
        ...
        assert ABC.objects.first().is_online == False
    
    

    【讨论】:

    • 你能再解释一下吗?
    猜你喜欢
    • 1970-01-01
    • 2014-07-23
    • 2013-08-06
    • 2017-05-10
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多