如何将mock.patch移动到setUp?

时间:2015-01-29 19:48:55

标签: python unit-testing mocking

我有以下两个单元测试:

    @mock.patch('news.resources.generator.Generator.get_header')
    @mock.patch('news.scraper.bbc_spider.BBCSpider.save_scraped_rss_into_news_model')
    @mock.patch('news.scraper.bbc_spider.BBCSpider.get_news_urls')
    @mock.patch('requests.get')
    def test_get_header_is_called(self, req_get, spi_news, spi_save_rss, get_head):
        spi_news.return_value = {'x': 1}
        gen = Generator()
        gen.get()
        get_head.assert_called_with()

    @mock.patch('news.resources.generator.Generator.get_header')
    @mock.patch('news.scraper.bbc_spider.BBCSpider.save_scraped_rss_into_news_model')
    @mock.patch('news.scraper.bbc_spider.BBCSpider.get_news_urls')
    @mock.patch('requests.get')
    def test_task_url_is_save_scraped_rss_into_news_model(self, req_get, spi_news, spi_save_rss, get_head):
        spi_news.return_value = {'x': 1}
        gen = Generator()
        gen.get()
        tasks = self.taskqueue_stub.GetTasks("newstasks")
        self.assertEqual(tasks[0]['url'], '/v1/worker/save-scraped-rss-into-news-model')

正如您所看到的,有很多代码重复。有没有办法将mock.patch移动到setUp()?

Class TestGenerator(TestBase):
    def setUp(self):
        super(TestGenerator, self).setUp()
        mock.patch() ???

    def test_get_header_is_called(self, req_get, spi_news, spi_save_rss, get_head):
            spi_news.return_value = {'x': 1}
            gen = Generator()
            gen.get()
            get_head.assert_called_with()

    def test_task_url_is_save_scraped_rss_into_news_model(self, req_get, spi_news, spi_save_rss, get_head):
            spi_news.return_value = {'x': 1}
            gen = Generator()
            gen.get()
            tasks = self.taskqueue_stub.GetTasks("newstasks")
            self.assertEqual(tasks[0]['url'], '/v1/worker/save-scraped-rss-into-news-model')

1 个答案:

答案 0 :(得分:7)

这里有2个选项 - 首先,您可以将修补程序移到课程中:

@mock.patch('news.resources.generator.Generator.get_header')
@mock.patch('news.scraper.bbc_spider.BBCSpider.save_scraped_rss_into_news_model')
@mock.patch('news.scraper.bbc_spider.BBCSpider.get_news_urls')
@mock.patch('requests.get')
class TestGenerator(TestBase):
    def test_get_header_is_called(self, req_get, spi_news, spi_save_rss, get_head):
      pass

当你在课堂上的mock.patch系列中使用某些内容时,它的行为就好像你已经修补了每个以&#34; test&#34; 1 开头的方法。< / p>

您的另一个选择是在设置中启动修补程序。在一个虚构的例子中(为了节省打字),它看起来像这样:

class SomeTest(TestCase):
    def setUp(self):
        super(SomeTest, self).setUp()
        patch = mock.patch('foo.bar.baz')
        mock_baz = patch.start()  # may want to keep a reference to this if you need to do per-test configuration
        self.addCleanup(patch.stop)
在python2.7中添加了

addCleanup(太棒了!)。如果你不需要旧版本的python2.x,你应该使用它,因为它比替代品更强大。最简单的替代方法就是停止tearDown中的所有补丁:

class SomeTest(TestCase):
    def setUp(self):
        super(SomeTest, self).setUp()
        patch = mock.patch('foo.bar.baz')
        mock_baz = patch.start()  # may want to keep a reference to this if you need to do per-test configuration

    def tearDown(self):
        super(SomeTest, self).tearDown()
        mock.patch.stopall()

但您也可以保留对各个修补程序self.patch1 = mock.patch(...)的引用,然后根据需要在tearDown中单独停用该修补程序。

实际上,mock.TEST_PREFIX默认为"test"