問題描述
我有一個通過裝飾器連接的 signal_handler,就像這個非常簡單的:
I have a signal_handler connected through a decorator, something like this very simple one:
@receiver(post_save, sender=User,
dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
# do stuff
我想做的是用模擬庫 http://www.voidspace 模擬它.org.uk/python/mock/ 在測試中,檢查 django 調(diào)用它的次數(shù).我現(xiàn)在的代碼是這樣的:
What I want to do is to mock it with the mock library http://www.voidspace.org.uk/python/mock/ in a test, to check how many times django calls it. My code at the moment is something like:
def test_cache():
with mock.patch('myapp.myfile.signal_handler_post_save_user') as mocked_handler:
# do stuff that will call the post_save of User
self.assert_equal(mocked_handler.call_count, 1)
這里的問題是即使模擬了原始信號處理程序也會被調(diào)用,很可能是因為 @receiver
裝飾器在某處存儲了信號處理程序的副本,所以我模擬了錯誤的代碼.
The problem here is that the original signal handler is called even if mocked, most likely because the @receiver
decorator is storing a copy of the signal handler somewhere, so I'm mocking the wrong code.
所以問題是:我如何模擬我的信號處理程序以使我的測試工作?
So the question: how do I mock my signal handler to make my test work?
請注意,如果我將信號處理程序更改為:
Note that if I change my signal handler to:
def _support_function(*args, **kwargs):
# do stuff
@receiver(post_save, sender=User,
dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
_support_function(*args, **kwargs)
我改為模擬 _support_function
,一切都按預(yù)期工作.
and I mock _support_function
instead, everything works as expected.
推薦答案
所以,我最終得到了一種解決方案:模擬信號處理程序只是意味著將模擬本身連接到信號,所以這正是我做了:
So, I ended up with a kind-of solution: mocking a signal handler simply means to connect the mock itself to the signal, so this exactly is what I did:
def test_cache():
with mock.patch('myapp.myfile.signal_handler_post_save_user', autospec=True) as mocked_handler:
post_save.connect(mocked_handler, sender=User, dispatch_uid='test_cache_mocked_handler')
# do stuff that will call the post_save of User
self.assertEquals(mocked_handler.call_count, 1) # standard django
# self.assert_equal(mocked_handler.call_count, 1) # when using django-nose
請注意,mock.patch
中的 autospec=True
是必需的,以使 post_save.connect
能夠在 上正確工作MagicMock
,否則django會拋出一些異常,連接會失敗.
Notice that autospec=True
in mock.patch
is required in order to make post_save.connect
to correctly work on a MagicMock
, otherwise django will raise some exceptions and the connection will fail.
這篇關(guān)于如何模擬 django 信號處理程序?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!