Python mock library: Decryption

In a previous post, I talked about my talk at hsvpy.  In the next few posts, I’m going to provide some examples of using the mock library.  These are going to be short and sweet.  They will provide several examples for those interested in doing this.

Mocking Out Decryption

Keys

In one of my personal projects, I am using encryption to encrypt and decrypt a file that lives on my local filesystem.  One of my classes takes a password to decrypt a file.

I want to test what happens when the KeyConfig constructor runs a function within it called “decrypt_file” and fails.

Since this decrypt_file function gets called over and over in every test case (since every test case instantiates a KeyConfig object and that function call happens in its constructor), I want my mock to apply for every test case in my test class.  Python’s TestCase class has built-in support for running a function before and after every single test case in your class.  Those functions are called “setUp” and “tearDown” (case is important!).

Here’s what I do in my setup to make sure every test case mocks out the decrypt_file function:

And here’s what I do to stop that mock behavior after every test case:

I have the name of my module in a global variable to my test file called MODULE.  The function to mock out is “decrypt_file”.  This is what you are seeing set to the “decrypt_patch” variable.  I have to start that patch by using the start() function, which returns that mocked object.

Note this is an alternative to using the @patch decorator.  I use the above approach when I need to use the decorator for every single test case inside my class.  I don’t want to have to copy-paste that patch above every test function, so I just enable it for the entire class.

I can make the mock do something different within each test case by changing the mock_decrypt variable, which holds my mock object.

In this test case, I make the decrypt function raise a ValueError exception.  I knew to do this based on my playing with the decrypt function before I tested it.  It raises a ValueError when something goes wrong… so I’m making my mock do the same thing, faking out an error condition.

I then call my KeyConfig class’s constructor, passing in a password of “password” (yes, I’m so secure… but hey, it’s just for testing… I don’t really use that password! 🙂 ).  I make sure that raises a ValueError by using the assertRaises function.  In this way, I’m making sure that the KeyConfig constructor handles a decrypt_file error appropriately.

Conclusion

This is a very simple example of testing an error condition in my KeyConfig class.  I can very easily and quickly verify that my constructor handles an error in the decrypt_file function appropriately (which, in this case, just raises a ValueError… so I’m just testing that I don’t hide an exception that is raised by the decrypt_file function).

This is one big use of the mock library.  I can simulate error conditions that would otherwise be hard to generate.  Using this, I can make sure my application still handles those edge cases appropriately for errors that very rarely happen.

Please follow and like us:
error

1
Leave a Reply

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
0 Comment authors
Python mock: Testing Lots of API Calls from main - Developer Automation Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
trackback

[…] This blog post assumes you have some knowledge about how the mock library works.  If you do not have a basic understanding of it, you can view Python’s documentation of the mock library, or my previous post using the mock library. […]