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

时间:2015-01-31 16:14:55

标签: python unit-testing mocking

在以下方法中,正确的行为是将<{1}}模型保存在之前将其id传递给异步任务队列以进行进一步处理。 否则,任务队列具有旧版本。

正如您所看到的,我犯了一个错误,并在将其ID发送到任务队列后保存模型。

news

我怎么可能测试呢? 只要保存模型,我的测试就会通过。但那是错的,顺序很重要,而且这个测试并没有抓住它!有没有办法用mock来实现这个目标?

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()

1 个答案:

答案 0 :(得分:0)

我使用unittest.mock framework中的patch进行了这类测试。

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

在你的情况下,钩子将是BBCSpider.taskqueue.Task,其side_effect是这样的:

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不是强制性的,但我喜欢在每次修补时使用它以避免愚蠢的错误。

如果代码包含一些错误(我无法毫不费力地测试它),我会道歉但我希望这个想法很明确。