DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Languages
  4. Injecting Mock Objects for Powerful Testing in Python

Injecting Mock Objects for Powerful Testing in Python

Matt  Cottingham user avatar by
Matt Cottingham
·
Feb. 20, 12 · Interview
Like (0)
Save
Tweet
Share
6.77K Views

Join the DZone community and get the full member experience.

Join For Free

The code discussed in this post can be found in the github repository.

While writing a module to handle Google ClientLogin recently, I wanted to test error handling by simulating error responses from the server. A simple but powerful way of doing this is to use the patching ability of the mock module.

The patching ability allows you to replace objects in scope with mocks so that different side effects or return values can be defined. Note that ‘object’ is used here in the pythonic sense – referring to entities such as modules and functions as well as class instances.

This is best illustrated by a real example, so in this post we’re going to mock the requests module and generate the exceptions described in the documentation when a request is made.

Our example module sends credentials to Google’s ClientLogin service in order to receive an authentication token, required for accessing certain Google services (such as C2DM). If you are interested, you can read more about ClientLogin on the Google Code page.

So, to request an authentication token from the ClientLogin service, you POST a set of parameters including email and password to the service endpoint. Here is a cut-down version of the code that initiates the authentication request:

class Authenticator(object):

    @staticmethod
    def generate_token(email, password, source,
                       account_type='GOOGLE', service='ac2dm'):

        """Returns an auth token for the supplied service."""

        base_url = 'https://www.google.com/accounts/ClientLogin'

        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }

        payload = {
            'Email': email,
            'Passwd': password,
            'source': source,
            'accountType': account_type,
            'service': service,
        }

        try:
            response = requests.post(base_url, data=payload, headers=headers)
        except(RequestException):
            raise


If the requests.post method throws an exception, we simply raise it to the caller rather than handling it immediately. In the requests module, RequestException is the base class from which others (like ConnectionError) inherit. We could improve our approach to exception handling but it is sufficient for this example.

These exceptions will be thrown from our mocked class, which is patched into the above code using a context manager:

import unittest2 as unittest
from requests.exceptions import RequestException, ConnectionError
from mock import patch
from clientlogin import Authenticator

class AuthenticationTests(unittest.TestCase):

    def test_connection_error(self):
        with patch.object(requests, 'post') as mock_method:
            mock_method.side_effect = ConnectionError
            Authenticator.generate_token('mail@example.com','password','tag')


Here, we have patched the post method in the requests module to throw a ConnectionError. You can think of this like code injection, where with acts as the closure.

In the real test method, we assert the exception was raised with another context manager:

def test_connection_error(self):
    with patch.object(requests, 'post') as mock_method:
        with self.assertRaises(RequestException):
            mock_method.side_effect = ConnectionError
            Authenticator.generate_token('mail@example.com','password','tag')


Here, we assert that the ConnectionError exception is raised to the caller, but we could easily have asserted a different condition. We could, for instance, have verified some exception handling logic.

As we’ve seen, mocking objects and methods in this manner is a simple but powerful way of running your code under different simulated conditions, allowing thorough testing of error-handling logic.

You can see the full module including tests and usage instructions at the github repository. For more information on the mock module, the full documentation is available.



Source: http://blueprintforge.com/blog/2012/01/08/python-injecting-mock-objects-for-powerful-testing/

Object (computer science) Python (language)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Host Hack Attempt Detection Using ELK
  • Introduction Garbage Collection Java
  • Orchestration Pattern: Managing Distributed Transactions
  • When Should We Move to Microservices?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: