Mocking a Constructor Helper Method in Python - python

I have defined my constructor in the following fashion.
def __init__(self):
//set some properties
...
self.helperMethod()
def helperMethod(self):
//Do some operation
I want to unittest the helper method, but in order to create the object to do the unit test, I need to run the __init__ method. However, doing this calls the helper method, which is undesirable, because this is the method that I need to test.
I tried mocking out the __init__ method, but I received the error that __init__ should return None and not MagicMock.
I also tried mocking out the helper method in the following way, but I could not find a way to manually restore the mocked method. MagicMock.reset_mock() does not do this.
SomeClass.helperMethod = MagicMock()
x = SomeClass()
[Need someway to undo the mock of helperMethod here]
What is the best way to unit test the helper method moving forward?

Have you tried capturing the original value of helperMethod ?
original_helperMethod = SomeClass.helperMethod
SomeClass.helperMethod = MagicMock()
x = SomeClass()
SomeClass.helperMethod = original_helperMethod
You can also use the patch decorator from the mock library
from mock import patch
class SomeClass():
def __init__(self):
self.helperMethod()
def helperMethod(self):
assert False, "Should not be called!"
x = SomeClass() # Will assert
with patch('__main__.SomeClass.helperMethod') as mockHelpMethod:
x = SomeClass() # Does not assert

Related

Mocking dependencies

I am Python newbie and trying to understand how to mock methods in UTs.
Here is my Test
test_module2.py
from module2 import A
import unittest
from unittest.mock import patch, MagicMock
class TestBulkLoad(unittest.TestCase):
#patch('simple_module.SimpleModuleClass')
def test_fun(self, a):
a.simpleFun = MagicMock(return_value=3)
testA = A()
testA.fun()
assert a.simpleFun.called
and I want to check that dependent SimpleModuleClass was mocked and invoked
module2.py
from simple_module import SimpleModuleClass
class A:
def fun(self):
print('I am from A class')
thing = SimpleModuleClass()
thing.simpleFun()
return -1
simple_module.py
class SimpleModuleClass:
def simpleFun(self):
print("I am from SimpleModuleClass")
return 0
I get AssertionError. Could you help me understand how to fix this?
a.simpleFun = MagicMock(return_value=3)
This line is only modifying the method of your mock object a (which you really should rename simpleModuleMock, since it's a mock of a SimpleModule class and not an A). It doesn't mock every instance of SimpleModule everywhere in your code, hence why an instance of SimpleModule is instantiated in A.fun() and not an instance of a mock of SimpleModule.
I would use dependency injection and pass an instance of SimpleModule to A.fun() instead of instantiating it inside of it, so that you can pass a mock. You could also make thing a public variable like so:
test_module2.py:
class TestBulkLoad(unittest.TestCase):
#patch('simple_module.SimpleModuleClass')
def test_fun(self, simpleModuleMock):
simpleModuleMock.simpleFun = MagicMock(return_value=3)
testA = A()
A.thing = simpleModuleMock
assert(testA.fun() == -1)
# assert simpleModule.simpleFun.called
assert isinstance(simpleModuleMock.simpleFun, MagicMock)
module2.py:
class A:
thing = SimpleModuleClass()
def fun(self):
print('I am from A class')
self.thing.simpleFun()
return -1
Note that there may exist better solutions with Python, but if there are, 1. I don't know of them, and 2. I doubt they're good practice.

Test instance of class that mocked method is called from in Python

I am mocking out a method of a class and want to test the instance of the class that the method was called from to test that the creation part of my function works as expected.
In my particular case do_stuff tries to write bar_instance to an Excel File and I don't want that to happen i.e.
def create_instance(*args):
return Bar(*args)
class Bar():
def __init__(self, *args):
self.args = args
def do_stuff(self):
pass
def foo(*args):
bar_instance = create_instance(*args)
bar_instance.do_stuff()
Then in a testing file
from unittest import TestCase
from unittest.mock import patch
from path.to.file import foo
class TestFoo(TestCase):
#patch('path.to.file.Bar.do_stuff')
def test_foo(self, mock_do_stuff):
test_args = [1]
_ = foo(*test_args)
# Test here the instance of `Bar` that `mock_do_stuff` was called from
# Something like
actual_args = list(bar_instance.args)
self.assertEqual(test_args, actual_args)
I put a break in the test function after foo(*test_args) is run but can't see any way from the mocked method of accessing the instance of Bar it was called from and am a bit stuck. I don't want to mock out Bar further up the code as I want to make sure the correct instance of Bar is being created.
In your code example, there are three things that might need testing: function create_instance, class Bar and function foo. I understand your test code such that you want to ensure that function foo calls do_stuff on the instance returned by create_instance.
Since the original create_instance function has control over the created instance, a solution of your problem is to mock create_instance such that your test gains control of the object that is handed over to foo:
import unittest
from unittest import TestCase
from unittest.mock import patch, MagicMock
from SO_60624698 import foo
class TestFoo(TestCase):
#patch('SO_60624698.create_instance')
def test_foo_calls_do_stuff_on_proper_instance (
self, create_instance_mock ):
# Setup
Bar_mock = MagicMock()
create_instance_mock.return_value = Bar_mock
# Exercise
foo(1, 2, 3) # args are irrelevant
# Verify
Bar_mock.do_stuff.assert_called()
if __name__ == '__main__':
unittest.main()
In addition, you might also want to test if foo passes the arguments correctly to create_instance. This could be implemented as a separate test:
...
#patch('SO_60624698.create_instance')
def test_foo_passes_arguments_to_create_instance (
self, create_instance_mock ):
# Setup
create_instance_mock.return_value = MagicMock()
# Exercise
foo(1, 22, 333)
# Verify
create_instance_mock.assert_called_with(1, 22, 333)
And, certainly, to complete the whole test of the object generation, you could test create_instance directly, by calling it and checking on the returned instance of Bar if it has used its arguments correctly for the construction of the Bar instance.
As patch returns an instance of Mock (or actually MagicMock, but it inherits the relevant methods from its base - Mock), you have the assert_called_with method available, which should do the trick.
Note that this method is sensitive to args/kwargs - you have to assert the exact same call.
Another note: it might be a better practice to use patch.object instead of patch here

Python magic method for variable being accessed?

I am looking for a magic method similar to the __get__ method, but in my case the variable is not inside another class, I want something like:
class A(object):
def __similar_to_get__(self):
print 'called'
return self
a = A()
b = a
>>> 'called'
Is it possible?
The reason I am asking this is, I am using a python mock library, let's say a function I am testing uses URI attribute, and I want to mock it to return different values in subsequent calls. Eg:
class WebService(obj):
URI = 'http://works.com'
def dowork(self):
call_api(self.URI)
For me to mock a failure I am using the mock library:
mock = MagicMock()
mock.side_effect = ['http://fail.com', 'http://works.com']
with patch('WebService.URI', mock):
# do the testing
But the problem is I can only get mock to return the urls by calling the callable mock() not just simply accessing mock
PS: I am a mock noob.
Not directly answering my own question, I managed to use a property to work around this:
from dps.px.pxpost import PxPost
mock = MagicMock()
mock.side_effect = ['http://doesnotexist', PxPost.URI]
def URI(self):
return mock()
with patch('django.conf.settings.CELERY_ALWAYS_EAGER', True, create=True):
with patch('dps.px.pxpost.PxPost.URI', property(URI)):
self.transaction.process()
for sub_transaction in self.transaction.sub_transactions.all():
self.assertTrue(isinstance(sub_transaction.state, CompletedSubTransaction))
self.assertTrue(sub_transaction.transaction_logs.count() > 0)
self.assertTrue(isinstance(self.transaction.state, CompletedTransaction))

Testing a function call inside the function using python unittest framework

I want to test this class using python unittest framework and also mockito.
class ISightRequestEngine(object):
def __init__(self, pInputString=None):
self.__params = (pInputString)
def openHTTPConnection(self):
pass
def __closeHTTPConnection(self):
pass
def testFunc(self):
print 'test function called'
def startEngine(self):
self.__params.parseinputString()
self.openHTTPConnection()
self.testFunc()
def processRequest(self, header = None):
pass
I wanted to test that function startEngine() calls testFunc().
Similar to what we do in our mocked class,
obj = mock(ISightRequestEngine)
obj.startEngine()
try:
verify(obj).startEngine()
except VerificationError:
Unfortunately this only verifies whether the startEngine function is called or not, but it does not give the actual function call and I cannot verify that whether the call to testFunc() has been made or not.
Is there any way to test this scenario?
I am new to testing world and framework.
In your example you are testing your mock.
You create a mock of ISightRequestingEngine
You call startEngine() method of that mock
You verify that the mocked object was called
What you want to do is:
Mock out testFunc()
Call startEngine()
Verify that testFunc() was called
I'm not familiar with mockito, but what from what I can make up from the documentation, I think you have to do something like the following:
from mockito import mock, verify
# Setup ---------------------------------------------
my_mock = mock(ISightRequestingEngine)
system_under_test = ISightRequestingEngine()
system_under_test.testFunc = my_mock.testfunc # Mock out only testFunc()
# Exercise ------------------------------------------
system_under_test.startEngine()
# Verify --------------------------------------------
verify(my_mock).testFunc()
Having similar such issue, where I am bit lost in writing the test case
class UserCompanyRateLimitValidation:
def __init__(self, user_public_key):
self.adapter = UserAdapter(user_public_key)
container = self.adapter.get_user_company_rate_limit()
super(UserCompanyRateLimitValidation, self).__init__(container,\
UserCompanyRateLimitValidation.TYPE)
I have to test this function. I have written test case something like this. I have tried to mock the UserAdapter class but I am not able to do so completely.
def test_case_1():
self.user_public_key = 'TEST_USER_PUBLIC_KEY_XXXXXX1234567890XXXXX'
UserAdapter_mock = mock(UserAdapter)
when(UserAdapter_mock).get_user_company_rate_limit().\
thenReturn(self.get_container_object())
self.test_obj = UserCompanyRateLimitValidation(self.user_public_key)
Here if you see I have mocked get_user_company_rate_limit() call from the testable function, container = self.adapter.get_user_company_rate_limit()
but I am still not able to figure out the way in which I can mock this call,
self.adapter = UserAdapter(user_public_key)

Mocking a class: Mock() or patch()?

I am using mock with Python and was wondering which of those two approaches is better (read: more pythonic).
Method one: Just create a mock object and use that. The code looks like:
def test_one (self):
mock = Mock()
mock.method.return_value = True
self.sut.something(mock) # This should called mock.method and checks the result.
self.assertTrue(mock.method.called)
Method two: Use patch to create a mock. The code looks like:
#patch("MyClass")
def test_two (self, mock):
instance = mock.return_value
instance.method.return_value = True
self.sut.something(instance) # This should called mock.method and checks the result.
self.assertTrue(instance.method.called)
Both methods do the same thing. I am unsure of the differences.
Could anyone enlighten me?
mock.patch is a very very different critter than mock.Mock. patch replaces the class with a mock object and lets you work with the mock instance. Take a look at this snippet:
>>> class MyClass(object):
... def __init__(self):
... print 'Created MyClass#{0}'.format(id(self))
...
>>> def create_instance():
... return MyClass()
...
>>> x = create_instance()
Created MyClass#4299548304
>>>
>>> #mock.patch('__main__.MyClass')
... def create_instance2(MyClass):
... MyClass.return_value = 'foo'
... return create_instance()
...
>>> i = create_instance2()
>>> i
'foo'
>>> def create_instance():
... print MyClass
... return MyClass()
...
>>> create_instance2()
<mock.Mock object at 0x100505d90>
'foo'
>>> create_instance()
<class '__main__.MyClass'>
Created MyClass#4300234128
<__main__.MyClass object at 0x100505d90>
patch replaces MyClass in a way that allows you to control the usage of the class in functions that you call. Once you patch a class, references to the class are completely replaced by the mock instance.
mock.patch is usually used when you are testing something that creates a new instance of a class inside of the test. mock.Mock instances are clearer and are preferred. If your self.sut.something method created an instance of MyClass instead of receiving an instance as a parameter, then mock.patch would be appropriate here.
I've got a YouTube video on this.
Short answer: Use mock when you're passing in the thing that you want mocked, and patch if you're not. Of the two, mock is strongly preferred because it means you're writing code with proper dependency injection.
Silly example:
# Use a mock to test this.
my_custom_tweeter(twitter_api, sentence):
sentence.replace('cks','x') # We're cool and hip.
twitter_api.send(sentence)
# Use a patch to mock out twitter_api. You have to patch the Twitter() module/class
# and have it return a mock. Much uglier, but sometimes necessary.
my_badly_written_tweeter(sentence):
twitter_api = Twitter(user="XXX", password="YYY")
sentence.replace('cks','x')
twitter_api.send(sentence)
Key points which explain difference and provide guidance upon working with unittest.mock
Use Mock if you want to replace some interface elements(passing args) of the object under test
Use patch if you want to replace internal call to some objects and imported modules of the object under test
Always provide spec from the object you are mocking
With patch you can always provide autospec
With Mock you can provide spec
Instead of Mock, you can use create_autospec, which intended to create Mock objects with specification.
In the question above the right answer would be to use Mock, or to be more precise create_autospec (because it will add spec to the mock methods of the class you are mocking), the defined spec on the mock will be helpful in case of an attempt to call method of the class which doesn't exists ( regardless signature), please see some
from unittest import TestCase
from unittest.mock import Mock, create_autospec, patch
class MyClass:
#staticmethod
def method(foo, bar):
print(foo)
def something(some_class: MyClass):
arg = 1
# Would fail becuase of wrong parameters passed to methd.
return some_class.method(arg)
def second(some_class: MyClass):
arg = 1
return some_class.unexisted_method(arg)
class TestSomethingTestCase(TestCase):
def test_something_with_autospec(self):
mock = create_autospec(MyClass)
mock.method.return_value = True
# Fails because of signature misuse.
result = something(mock)
self.assertTrue(result)
self.assertTrue(mock.method.called)
def test_something(self):
mock = Mock() # Note that Mock(spec=MyClass) will also pass, because signatures of mock don't have spec.
mock.method.return_value = True
result = something(mock)
self.assertTrue(result)
self.assertTrue(mock.method.called)
def test_second_with_patch_autospec(self):
with patch(f'{__name__}.MyClass', autospec=True) as mock:
# Fails because of signature misuse.
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
class TestSecondTestCase(TestCase):
def test_second_with_autospec(self):
mock = Mock(spec=MyClass)
# Fails because of signature misuse.
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
def test_second_with_patch_autospec(self):
with patch(f'{__name__}.MyClass', autospec=True) as mock:
# Fails because of signature misuse.
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
def test_second(self):
mock = Mock()
mock.unexisted_method.return_value = True
result = second(mock)
self.assertTrue(result)
self.assertTrue(mock.unexisted_method.called)
The test cases with defined spec used fail because methods called from something and second functions aren't complaint with MyClass, which means - they catch bugs, whereas default Mock will display.
As a side note there is one more option: use patch.object to mock just the class method which is called with.
The good use cases for patch would be the case when the class is used as inner part of function:
def something():
arg = 1
return MyClass.method(arg)
Then you will want to use patch as a decorator to mock the MyClass.

Categories

Resources