Reputation: 34297
I am trying to test a method in an already existing class. Within inputStreamThread
method in the Foo.crawler.crawlerapp.CrawlerApp
class the method addUrl
is called.
inputStreamThread
reads from stdin and then calls addUrl
addUrl
is also in the CrawlerApp
class
I was hoping to be able to use assert_called_with
on a mock addUrl
to check that inputStreamThread
is doing the right thing and calling addUrl
Trouble is I cannot get the syntax right for the mock of addUrl
within CrawlerApp
I used an example straight out of the mock docs but get the error shown below
As you can see I am also mocking stdin to be able to present test data on it
My question is, what code do I use to carry out this sort of test and not get the error shown?
import Foo.crawler.crawlerapp
from unittest import TestCase
from mock import patch, Mock
from mephistopheles.messageformat import EventDataFrame
from mephistopheles.messageformat.types import adservers as pbufs
import time
import sys
class testDeserial(TestCase):
def generate_dummy_auction_event(self,url):
adunitinfo = pbufs.AdUnitInfo(index_on_page=0, url=url)
geoloc = pbufs.GeoLocation(country="DE", region="low")
userinfo = pbufs.UserInfo(user_hash=1,
ip_octets=1,
geolocation=geoloc,
language="en")
auctioninfo = pbufs.AuctionInfo(timestamp=int(time.time()),
user=userinfo,
ad_unit=adunitinfo)
return auctioninfo
def setUp(self):
pass
@patch.object(Foo.crawler.crawlerapp.CrawlerApp,'addUrl')
def test_check_url(self, MaddUrl):
url_a = "http://audaxing.wordpress.com"
dummy_event = self.generate_dummy_auction_event(url_a)
with patch("sys.stdin") as mock_stdin:
mock_stdin.read.return_value = dummy_event
ca._running = True
input_thread = threading.Thread(target=self.inputStreamThread)
input_thread.start()
time.sleep(0.5)
ca._running = False
MaddUrl.assert_called_with(url_a)
The test run output....
$ bin/tests --tests-pattern=test_deserialize
Test-module import failures:
Module: Foo.crawler.tests.test_deserialize
Traceback (most recent call last):
File "/home/jamie/svn/Foo/crawler.buildout/trunk/src/Foo.crawler/Foo/crawler/tests/test_deserialize.py", line 11, in <module>
class testDeserial(TestCase):
File "/home/jamie/svn/Foo/crawler.buildout/trunk/src/Foo.crawler/Foo/crawler/tests/test_deserialize.py", line 28, in testDeserial
@patch.object(Foo.crawler.crawlerapp.CrawlerApp,'addUrl')
AttributeError: 'function' object has no attribute 'object'
Test-modules with import problems:
Foo.crawler.tests.test_deserialize
Total: 0 tests, 0 failures, 0 errors in 0.000 seconds.
Upvotes: 6
Views: 15985
Reputation: 34297
I figured out what to do in the end. Bit of a monkey at a typewriter thing, not sure why I have to use "patch" and not "patch.object" or why I need to make Mock() objects first. I just tried every possible pattern from the examples in the docs
Anyway, this works for me
def test_check_url(self):
url_a = "http://audaxing.wordpress.com"
dummy_event = self.generate_dummy_auction_event(url_a)
with patch("sys.stdin") as mock_stdin:
MaddUrl = Mock()
Minit = Mock(return_value=None)
with patch('Foo.crawler.crawlerapp.CrawlerApp.__init__', Minit, create=True):
with patch('Foo.crawler.crawlerapp.CrawlerApp.addUrl', MaddUrl, create=True):
ca = Foo.crawler.crawlerapp.CrawlerApp(1)
mock_stdin.read.return_value = EventDataFrame(1, "TOKEN1", dummy_event.SerializeToString()).to_bytes()
ca._running = True
input_thread = threading.Thread(target=ca.inputStreamThread)
input_thread.start()
time.sleep(0.5)
ca._running = False
MaddUrl.assert_called_with(url_a)
Upvotes: 4
Reputation: 14853
I would say the following:
@patch.object... #1
def test_check... #2
is equivalent to
def test_check... #2
test_check.object = ... #1
And one can not assign new attributes to function objects.
Upvotes: -1