Python 如何测试在传递到任务队列之前是否保存了模型?

Python 如何测试在传递到任务队列之前是否保存了模型?,python,unit-testing,mocking,Python,Unit Testing,Mocking,在下面的方法中,正确的行为是保存新闻模型,然后将其id传递给异步任务队列进行进一步处理。 否则,任务队列将使用旧版本 如您所见,我犯了一个错误,在将模型的id发送到任务队列后正在保存模型 def save_scraped_body_into_model(url_string): news = ndb.Key(urlsafe=url_string).get() ... news.body = result news.stage = 1

在下面的方法中,正确的行为是保存新闻模型,然后将其id传递给异步任务队列进行进一步处理。 否则,任务队列将使用旧版本

如您所见,我犯了一个错误,在将模型的id发送到任务队列后正在保存模型

def save_scraped_body_into_model(url_string):
        news = ndb.Key(urlsafe=url_string).get()
        ...
        news.body = result
        news.stage = 1
        taskqueue.Task(url='/api/v1.0/worker/bbc-stage-2', headers=header,
                           payload=json.dumps({'news_url_string': news.key.urlsafe()})).add(queue_name='newstasks')
        news.put()
我怎么可能测试它呢? 只要模型被保存,我下面的测试就通过了。但这是错误的,顺序很重要,而且这个测试没有捕获它!!!有没有办法用mock实现这一点

def test_news_instance_saved_before_next_stage(self, get_head):
        BBCSpider.save_scraped_body_into_model(self.news.key.urlsafe())
        context = ndb.get_context()
        context.clear_cache()
        news = ndb.Key(urlsafe=self.news.key.urlsafe()).get()
        self.assertEqual(news.stage, 1)

我正在使用来自的补丁进行此类测试

当我需要做这样的测试时,我要做的第一件事就是寻找一个可以放置钩子的点。然后我修补钩子,并使用side_-effect回调进行测试

在您的例子中,钩子将是BBCSpider.taskqueue.Task,其副作用如下:

lambda *args,**kwargs: self.assertEqual(1, ndb.Key(urlsafe=self.news.key.urlsafe()).get().stage)
所以你的测试变成:

@patch('BBCSpider.taskqueue.Task', autospec=True)
def test_news_instance_saved_before_next_stage(self, get_head, mock_task):
    def check_if_model_saved(*args,**kwargs):
        news = ndb.Key(urlsafe=self.news.key.urlsafe()).get()
        self.assertEqual(news.stage,1)
    mock_task.side_effect = check_if_model_saved
    BBCSpider.save_scraped_body_into_model(self.news.key.urlsafe())
    self.assertTrue(mock_task.called)
注意:autospec=True不是强制性的,但我喜欢在每次做补丁时使用它,以避免愚蠢的错误


很抱歉,如果代码中包含一些错误,我无法不费吹灰之力进行测试,但我希望想法是明确的。

我不知道我是否迟到了,但如果您仍对我感兴趣,我已发布了一个答案。感谢您的回复。这是非常有趣的方法。因此,即使我在最后保存news.put,因为mock.hook出现在前面,该hook的副作用仍然会认为模型未保存?即使它是在一行之后保存的?当然:副作用等self.assertEqualnews.stage,当您的代码在news.put调用之前调用taskqueue.Task等时,将执行1