I have the following two unit tests:
@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')
As you can see there is a lot of code repetition. Is there a way I could move the mock.patch to the 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')
You have 2 options here -- First, you could move the patching to the class:
@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
when you use something in the mock.patch
family on the class, it behaves as if you had patched each method that starts with "test"1 individually.
Your other option is to start the patches in setup. In a fictitious example (to save typing), it looks like this:
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)
addCleanup
was added in python2.7 (and is fantastic!). If you don't need older versions of python2.x, you should use it as it is more robust than the alternatives. The easiest alternative is to just stop all patches in 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()
but you can also keep references to individual patches self.patch1 = mock.patch(...)
and then stop that one individually in tearDown
as necessary.
1Actually, mock.TEST_PREFIX
which defaults to "test"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With