How to mock a method inside another module during unit testing - django

In one of my test case the flow requires that a customer provision process wherein the call goes to the api.py file where in the response is saved from the function create_t_customer like following:
In api.py file it is using the method create_t_customer imported from file customer.py
response = create_t_customer(**data)
In customer.py file the code for function is
def create_t_customer(**kwargs):
t_customer_response = Customer().create(**kwargs)
return t_customer_response
I want to mock the function create_t_customer inside the unittest.
Current I have tried the following but it doesn't seem to be working
class CustomerTest(APITestCase):
#mock.patch("apps.dine.customer.create_t_customer")
def setUp(self,mock_customer_id):
mock_customer_id.return_value = {"customer":1}
But this is not able to mock the function.

You should mock it inside the file it is imported. For example you have declared create_t_customer in customer.py and using it in api.py. You should mock it from api instead of customer module like this.
class CustomerTest(APITestCase):
#mock.patch("x.y.api.create_t_customer")
def test_xyz(self, mock_customer_id):
mock_customer_id.return_value = {"customer":1}

Related

pytest mock, mocking a class and overriding a method does not carry over to an instance of the class

I am trying to mock a class and also to control the return value of one of the methods. In the MUT the class gets instantiated and I am finding that while the method calls succeed I can not find any way to control the return value.
All the examples I can find show mocking the class methods or mocking a single method with patch object.
I could monkeypatch the entire class and not use Mock, but it seems to me that there must be a way to do this using Mock and have the benefit of all the assert_called*
Here is the simplest example I can come up with that demonstrates the problem. In practice it would be the MUT that instantiates the class but the problem is the same.
from unitest.mock import Mock
mock_class = Mock()
mock_class.method = Mock(return_value=2)
print("Class", mock_class.method(None))
instance = mock_class()
print("Instance", instance.method())
Class 2
Instance <Mock name='mock().method()' id='140446103686160'>
Also tried
from unitest.mock import Mock
mock_class = Mock()
mock_class.method = lambda s: 2
print("Class", mock_class.method(None))
instance = mock_class()
print("Instance", instance.method())
and
from unitest.mock import Mock
mock_class = Mock(method = lambda s: 2)
print("Class", mock_class.method(None))
instance = mock_class()
print("Instance", instance.method())
Same results.
Is there a way to add a method to a Mock class so that it exists in any subsequent instance of the class, or at least control the return value of an instance method for a mocked class?

Accessing methods from module in resque job

Hi I have to access a method from a module in a resuq job, I keep getting this error: method not accessible. Am I using the module incorrectly??
class TestResqueJob
include TestModule
#queue = :test_resque
def self.perform(params)
method_from_module
end
end
module TestModule
def method_from_module
puts "test"
end
end
It seems that you are trying to call an instance method inside a public method. I f you want your module methods to be class methods change include to extend
class TestResqueJob
extend TestModule
#queue = :test_resque
def self.perform(params)
method_from_module
end
end
this will make all the methods you have defined in the module as class methods

python mock patch : a method of instance is called?

In python 2.7, I have this function
from slacker import Slacker
def post_message(token, channel, message):
channel = '#{}'.format(channel)
slack = Slacker(token)
slack.chat.post_message(channel, message)
with mock and patch, I can check that the token is used in Slacker class
import unittest
from mock import patch
from slacker_cli import post_message
class TestMessage(unittest.TestCase):
#patch('slacker_cli.Slacker')
def test_post_message_use_token(self, mock_slacker):
token = 'aaa'
channel = 'channel_name'
message = 'message string'
post_message(token, channel, message)
mock_slacker.assert_called_with(token)
how I can check the string use in post_message ?
I try with
mock_slacker.chat.post_message.assert_called_with('#channel_name')
but I get
AssertionError: Expected call: post_message('#channel_name')
Not called
You need to be specific about where the call is taking place. The code is:
slack.chat.post_message
So, as slack is an instance of the mocked class Slacker, you'll need to use return_value to ensure you're talking about that instance:
mock_slacker.return_value.chat.post_message.assert_called_with
You've patched 'slacker_cli.Slacker' so mock_slacker is a patched class. The call itself is taking place on an instance of that patched class. Calling a class returns an instance, hence the use of return_value.

Mock object issue

I am using mock from voidspace and trying to execute some tests using unittest2 and the behaviour is strange. When i use "#patch.object(Test,'asd')" as a patch i get the mock object in the function arguments.
If i use #patch.object(Test,'asd',new_fun) as patch i dont get the one of the parameters.
I am using mock-1.0.1
Here you can see a small sample of code that exemplifies the problem.
I want to try to understand if this issue is a problem with the way i do the patch or if this is a problem in the library.
import unittest2 as unittest
from mock import patch
class Test:
def asd(self, a, b =""):
print "1"
class Test1:
def kk(self, l):
Test().asd("1")
def kk1(self, l):
Test().asd("1","1")
#patch.object(Test,'asd')
class MockClassUT(unittest.TestCase):
def test_stat_process(self, my_mock):
t = Test1()
def test_stat_process1(self, my_mock):
t = Test1()
def test_stat_process2(self, my_mock):
t = Test1()
def new_fun(*args, **kwargs):
print "1"
#patch.object(Test,'asd',new_fun)
class MockClassUT1(unittest.TestCase):
def test_stat_process(self, my_mock):
t = Test1()
t.kk("1")
my_mock.assert_called_with("k")
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(MockClassUT)
suite = unittest.TestSuite()
for name in testnames:
suite.addTest(MockClassUT(name))
testnames = testloader.getTestCaseNames(MockClassUT1)
for name in testnames:
suite.addTest(MockClassUT1(name))
print testnames
unittest.TextTestRunner(verbosity=2).run(suite)
This is expected behaviour. You have mocked it as a class decorator and you've also specified the new function new_fun. As such the mocked object won't be passed to each of the methods in the test class.
This means you can't expect my_mock as parameter there and it also means you can't write assertions using my_mock.
Furthermore, as an aside, your mocked method new_fun doesn't have the same signature as the method you're mocking (asd). The method asd expects self, a, b="" whereas new_fun doesn't have arguments so I expect an issue to come up there as well when the mocked method is called.

Unmocking a mocked object in Django unit tests

I have several TestCase classes in my django application. On some of them, I mock out a function which calls external resources by decorating the class with #mock.patch, which works great. One TestCase in my test suite, let's call it B(), depends on that external resource so I don't want it mocked out and I don't add the decorator. It looks something like this:
#mock.patch("myapp.external_resource_function", new=mock.MagicMock)
class A(TestCase):
# tests here
class B(TestBase):
# tests here which depend on external_resource_function
When I test B independently, things work as expected. However, when I run both tests together, A runs first but the function is still mocked out in B. How can I unmock that call? I've tried reloading the module, but it didn't help.
Patch has start and stop methods. Based on what I can see from the code you have provided, I would remove the decorator and use the setUp and tearDown methods found in the link in your classes.
class A(TestCase):
def setUp(self):
self.patcher1 = patch('myapp.external_resource_function', new=mock.MagicMock)
self.MockClass1 = self.patcher1.start()
def tearDown(self):
self.patcher1.stop()
def test_something(self):
...
>>> A('test_something').run()
Great answer. With regard to Ethereal's question, patch objects are pretty flexible in their use.
Here's one way to approach tests that require different patches. You could still use setUp and tearDown, but not to do the patch.start/stop bit.
You start() the patches in each test and you use a finally clause to make sure they get stopped().
Patches also support Context Manager stuff so that's another option, not shown here.
class A(TestCase):
patcher1 = patch('myapp.external_resource_function', new=mock.MagicMock)
patcher2 = patch('myapp.something_else', new=mock.MagicMock)
def test_something(self):
li_patcher = [self.patcher1]
for patcher in li_patcher:
patcher.start()
try:
pass
finally:
for patcher in li_patcher:
patcher.stop()
def test_something_else(self):
li_patcher = [self.patcher1, self.patcher2]
for patcher in li_patcher:
patcher.start()
try:
pass
finally:
for patcher in li_patcher:
patcher.stop()