I'm a newbie to python and the app engine.
I have this code that sends an email based on request params after some auth logic. in my Unit tests (i'm using GAEUnit), how do I confirm an email with specific contents were sent? - i.e. how do I mock the emailer with a fake emailer to verify send was called?
class EmailHandler(webapp.RequestHandler):
def bad_input(self):
self.response.set_status(400)
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write("<html><body>bad input </body></html>")
def get(self):
to_addr = self.request.get("to")
subj = self.request.get("subject")
msg = self.request.get("body")
if not mail.is_email_valid(to_addr):
# Return an error message...
# self.bad_input()
pass
# authenticate here
message = mail.EmailMessage()
message.sender = "[email protected]"
message.to = to_addr
message.subject = subj
message.body = msg
message.send()
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write("<html><body>success!</body></html>")
And the unit tests,
import unittest
from webtest import TestApp
from google.appengine.ext import webapp
from email import EmailHandler
class SendingEmails(unittest.TestCase):
def setUp(self):
self.application = webapp.WSGIApplication([('/', EmailHandler)], debug=True)
def test_success(self):
app = TestApp(self.application)
response = app.get('http://localhost:8080/[email protected]&body=blah_blah_blah&subject=mySubject')
self.assertEqual('200 OK', response.status)
self.assertTrue('success' in response)
# somehow, assert email was sent
You could also override the _GenerateLog
method in the mail_stub
inside AppEngine.
Here is a parent TestCase class that I use as a mixin when testing that e-mails are sent:
from google.appengine.api import apiproxy_stub_map, mail_stub
__all__ = ['MailTestCase']
class MailTestCase(object):
def setUp(self):
super(MailTestCase, self).setUp()
self.set_mail_stub()
self.clear_sent_messages()
def set_mail_stub(self):
test_case = self
class MailStub(mail_stub.MailServiceStub):
def _GenerateLog(self, method, message, log, *args, **kwargs):
test_case._sent_messages.append(message)
return super(MailStub, self)._GenerateLog(method, message, log, *args, **kwargs)
if 'mail' in apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map:
del apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map['mail']
apiproxy_stub_map.apiproxy.RegisterStub('mail', MailStub())
def clear_sent_messages(self):
self._sent_messages = []
def get_sent_messages(self):
return self._sent_messages
def assertEmailSent(self, to=None, sender=None, subject=None, body=None):
for message in self.get_sent_messages():
if to and to not in message.to_list(): continue
if sender and sender != message.sender(): continue
if subject and subject != message.subject(): continue
if body and body not in message.textbody(): continue
return
failure_message = "Expected e-mail message sent."
args = []
if to: args.append('To: %s' % to)
if sender: args.append('From: %s' % sender)
if subject: args.append('Subject: %s' % subject)
if body: args.append('Body (contains): %s' % body)
if args:
failure_message += ' Arguments expected: ' + ', '.join(args)
self.fail(failure_message)
After that, a sample test case might look like:
import unittest, MailTestCase
class MyTestCase(unittest.TestCase, MailTestCase):
def test_email_sent(self):
send_email_to('[email protected]') # Some method that would send an e-mail.
self.assertEmailSent(to='[email protected]')
self.assertEqual(len(self.get_sent_messages()), 1)
A very short introduction provides PyPI: MiniMock 1.0. It's a very small library to establish mocks.
Good luck!
Just use the following to get all messages sent since activating the mail stub.
from google.appengine.api import apiproxy_stub_map
sent_messages = apiproxy_stub_map.apiproxy._APIProxyStubMap__stub_map['mail'].get_sent_messages()
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