【问题标题】:Django testing custom signal arguments with assertIsInstance: AssertionError: <class 'path.to.Foo'> is not an instance of <class 'path.to.Foo'>Django 使用 assertIsInstance 测试自定义信号参数:AssertionError: <class 'path.to.Foo'> is not an instance of <class 'path.to.Foo'>
【发布时间】:2025-12-05 05:55:01
【问题描述】:

我正在使用 Django 3.2

我编写了一个引发自定义事件的应用,并且正在为这些应用编写测试。

这是我的代码的相关部分:

class TestAppModel(TestCase):
    # .. set up instance variables etc.

    def test_liked_signal_emits_correct_data(self):
    
        self.signal_was_called = False
        self.sender = None
        self.instance = None   
        self.event_type = None
        self.actor = None

        def handler(sender, instance, event_type, actor, **kwargs):
            self.signal_was_called = True
            self.sender = sender
            self.instance = instance   
            self.event_type = event_type
            self.actor = actor         
            
        item_liked.connect(handler)

        self.daddy.like(self.admin_user)

 
        # Check that the sender is a Foo
        self.assertIsInstance(self.sender, Foo) # <- Nonsensical error emitted here

当我运行测试时,我收到错误消息:

AssertionError: 不是

的实例

这显然是一条无意义的错误消息,无法帮助我解决问题。

我的问题是为什么我无法使用assertIsInstance 检查实例类型,以及如何检查信号接收器中的类类型?

【问题讨论】:

    标签: python django python-unittest django-testing django-signals


    【解决方案1】:

    信号中的sender 通常是实例的。因此,您编写 self.assertIsInstance(self.sender, Foo) 等同于编写 self.assertIsInstance(Foo, Foo) 这当然是不正确的,因为 Foo 不是 Foo 的实例(它可能是 objecttypeModelBase 的实例( Model)) 的元类。例如看下面的sn-p:

    class Foo:
        pass
    
    print(isinstance(Foo, Foo)) # False
    print(isinstance(Foo, object)) # True
    print(isinstance(Foo, type)) # True
    

    您想使用assertIs 而不是assertIsInstance

    class TestAppModel(TestCase):
        # .. set up instance variables etc.
    
        def test_liked_signal_emits_correct_data(self):
        
            self.signal_was_called = False
            self.sender = None
            self.instance = None   
            self.event_type = None
            self.actor = None
    
            def handler(sender, instance, event_type, actor, **kwargs):
                self.signal_was_called = True
                self.sender = sender
                self.instance = instance   
                self.event_type = event_type
                self.actor = actor         
                
            item_liked.connect(handler)
    
            self.daddy.like(self.admin_user)
    
     
            # Check that the sender is a Foo
            self.assertIs(self.sender, Foo) # The sender should be Foo itself
            self.assertIsInstance(self.instance, Foo) # The instance should be an instance of Foo
    

    【讨论】:

    • 最后,我能够弄清楚发生了什么,我使用一个包裹模拟对象的 ContextManger 类重写了它 - 但一如既往地感谢您的回答!
    • @HomunculusReticulli 我想补充您的问题,但您的问题总是有一个适当的 mre。 :)