Skip to main content
 首页 » 编程设计

python之Django 断言调用了 post_save 信号

2024年10月01日36EasonJim

我试图断言在保存我的客户端模型的实例时调用 post_save 信号接收器。

信号接收器如下所示:

# reports/signals.py 
 
@receiver(post_save, sender=Client) 
def create_client_draft(sender, instance=None, created=False, **kwargs): 
    """Guarantees a DraftSchedule exists for each Client post save""" 
    print('called')  # Log to stdout when called 
    if created and not kwargs.get('raw', False): 
        DraftSchedule.objects.get_or_create(client=instance) 

我已经设置了一个看起来像这样的测试

@pytest.mark.django_db 
@patch('reports.signals.create_client_draft') 
def test_auto_create_draftschedule_on_client_creation(mock_signal): 
    client = mixer.blend(Client)  # Creates a Client with random data 
    assert mock_signal.call_count == 1 

我希望这个测试能够通过,因为 called 打印语句在测试运行时出现在捕获的标准输出中。

但是,测试运行器似乎认为我的模拟函数根本没有被调用过。

mock_signal = <MagicMock name='create_client_draft' id='139903470431088'> 
 
    @pytest.mark.django_db 
    @patch('reports.signals.create_client_draft') 
    def test_auto_create_draftschedule_on_client_creation(mock_signal): 
        client = mixer.blend(Client) 
>       assert mock_signal.call_count == 1 
E       AssertionError: assert 0 == 1 
E        +  where 0 = <MagicMock name='create_client_draft' id='139903470431088'>.call_count 
 
reports/tests/test_signals.py:36: AssertionError 
---------------------------------------------------------------------------------------------------------------------------------------------------- Captured stdout call ----------------------------------------------------------------------------------------------------------------------------------------------------- 
called 

打印语句似乎表明该函数在测试期间被调用,而测试断言则表明并非如此。我是否在模拟库中遗漏了一些明显的东西?

请您参考如下方法:

修补模拟对象仅适用于在运行时查找方法的调用者。信号处理程序保存在表中,因此它们不会查找您的模拟版本。

这有点老套,但您可以让信号处理程序调用辅助函数。然后可以模拟辅助函数。

# reports/signals.py 
 
@receiver(post_save, sender=Client) 
def create_client_draft_handler(sender, instance=None, created=False, **kwargs): 
    create_client_draft(sender, instance, created, **kwargs) 
 
def create_client_draft(sender, instance=None, created=False, **kwargs): 
    """Guarantees a DraftSchedule exists for each Client post save 
 
        This function can be mocked, because it's called by name. 
    """ 
    print('called')  # Log to stdout when called 
    if created and not kwargs.get('raw', False): 
        DraftSchedule.objects.get_or_create(client=instance)