patching instantiated object method call in python - python

Suppose we have
import XYZ
Class(object):
def __init__(self):
pass
def some_call(self)
#other logic
obj = XYZ()
obj.do_something()
In my unittest I'm trying to patch XYZ, and the call to do_something. I want to call some_call in my unittest because I have other logic to perform, but specifically the one instance and method call on the instance I want to bypass.

Related

calling a method inside a class from a different file

I am trying to implement python classes and objects in my application code. Currently, I have a file that includes all the frequently used functions. I import them in another file.
funcs.py
class name1():
def func1(x):
return x
def func2(y):
return y
....
file1.py
from funcs import func1
from funcs import func2
I'd like to organize the code in class, method and attributes and then invoke them in different files.
How do I call a method within a class from another file? What changes do I need to make in funcs.py file?
If you want to call a method within a class, first you have to instantiate an object of that class, and then call the method in reference to the object. Below is not an ideal implementation but it's just for example.
example.py
class MyClass:
def my_method(self):
print('something')
object1 = MyClass()
object1.my_method()
Then when you want to call the method in another file you have to first import them.
another.py
from .example import MyClass
object2 = MyClass()
object2.my_method()
If you just want to call the method without having to create an object first you can use #staticmethod.
class MyClass:
#staticmethod
def my_method(self):
print('something')
MyClass.my_method()
Yet as I said this is not the ideal implementation. As #juanpa.arrivillaga said ideally you cannot just throw in any method and bundle them into a single class. The content of a class is all related to the object you want to define as a class.

Class decorator not being called everytime

A seemingly easy thing which i cant get around.
registry = {}
def register(cls):
registry[cls.__clsid__] = cls
print cls
return cls
#register
class Foo(object):
__clsid__ = "123-456"
def bar(self):
pass
c=Foo()
d=Foo()
e=Foo()
Output:
<class '__main__.Foo'>
Now i expect decorator to be called 3 times.Why has it been called only once.
A class decorator is applied when the class is created, not each time an instance is created.
The #register line applies to the class Foo(object): statement only. This is run just once, when the module is imported.
Creating an instance does not need to re-run the class statement because instances are just objects that keep a reference to the class (type(c) returns the Foo class object); instances are not 'copies' of a class object.
If you want to register instances you'll either have to do so in the __init__ or the __new__ method of a class (which can be decorated too). __new__ is responsible for creating the instance, __init__ is the hook called to initialise that instance.
The class decorator is being applied to the class itself, and it is applied only once, when the class is defined. Basically, it processes the class definition and produces a new class.
So you'd only process it once.

Calling a test method in another TestClass

Hi I have the following test classes
logintests.py:
class SignOnTests(BaseTest):
def test_login_info(self):
#some code
passwordtests.py:
class ResetPasswordTests(unittest.TestCase):
def test_mytest(self):
#somecode
#Should Call SignOnTests.test_login_info()
I've tried putting on passwordtests.py:
from logintests import SignOnTests
But keep gettingTypeError: unbound method test_login_info() must be called with SignOnTests instance as first argument (got nothing instead)
Is it possible to call a test method within another module?

Mock a class and a class method in python unit tests

I'm using python's unittest.mock to do some testing in a Django app. I want to check that a class is called, and that a method on its instance is also called.
For example, given this simplified example code:
# In project/app.py
def do_something():
obj = MyClass(name='bob')
return obj.my_method(num=10)
And this test to check what's happening:
# In tests/test_stuff.py
#patch('project.app.MyClass')
def test_it(self, my_class):
do_something()
my_class.assert_called_once_with(name='bob')
my_class.my_method.assert_called_once_with(num=10)
The test successfully says that my_class is called, but says my_class.my_method isn't called. I know I'm missing something - mocking a method on the mocked class? - but I'm not sure what or how to make it work.
Your second mock assertion needs to test that you are calling my_method on the instance, not on the class itself.
Call the mock object like this,
my_class().my_method.assert_called_once_with(num=10)
^^
A small refactoring suggestion for your unittests to help with other instance methods you might come across in your tests. Instead of mocking your class in each method, you can set this all up in the setUp method. That way, with the class mocked out and creating a mock object from that class, you can now simply use that object as many times as you want, testing all the methods in your class.
To help illustrate this, I put together the following example. Comments in-line:
class MyTest(unittest.TestCase):
def setUp(self):
# patch the class
self.patcher = patch('your_module.MyClass')
self.my_class = self.patcher.start()
# create your mock object
self.mock_stuff_obj = Mock()
# When your real class is called, return value will be the mock_obj
self.my_class.return_value = self.mock_stuff_obj
def test_it(self):
do_something()
# assert your stuff here
self.my_class.assert_called_once_with(name='bob')
self.mock_stuff_obj.my_method.assert_called_once_with(num=10)
# stop the patcher in the tearDown
def tearDown(self):
self.patcher.stop()
To provide some insight on how this is put together, inside the setUp method we will provide functionality to apply the patch across multiple methods as explained in the docs here.
The patching is done in these two lines:
# patch the class
self.patcher = patch('your_module.MyClass')
self.my_class = self.patcher.start()
Finally, the mock object is created here:
# create your mock object
self.mock_stuff_obj = Mock()
self.my_class.return_value = self.mock_stuff_obj
Now, all your test methods can simply use self.my_class and self.mock_stuff_obj in all your calls.
This line
my_class.my_method.assert_called_once_with(num=10)
will work if my_method is a class method.
Is it the case?
Otherwise, if my_method is just an normal instance method, then you will need to refactor the function do_something to get hold of the instance variable obj
e.g.
def do_something():
obj = MyClass(name='bob')
return obj, obj.my_method(num=10)
# In tests/test_stuff.py
#patch('project.app.MyClass')
def test_it(self, my_class):
obj, _ = do_something()
my_class.assert_called_once_with(name='bob')
obj.my_method.assert_called_once_with(num=10)

Python: How to distinguish between inherited methods

Newbie Python question. I have a class that inherits from several classes, and some of the specialization classes override some methods from the base class. In certain cases, I want to call the unspecialized method. Is this possible? If so, what's the syntax?
class Base(object):
def Foo(self):
print "Base.Foo"
def Bar(self):
self.Foo() # Can I force this to call Base.Foo even if Foo has an override?
class Mixin(object):
def Foo(self):
print "Mixin.Foo"
class Composite(Mixin, Base):
pass
x = Composite()
x.Foo() # executes Mixin.Foo, perfect
x.Bar() # indirectly executes Mixin.Foo, but I want Base.Foo
you can specifically make the call you want using the syntax
Base.Foo(self)
in your case:
class Base(object):
# snipped
def Bar(self):
Base.Foo(self) # this will now call Base.Foo regardless of if a subclass
# overrides it
# snipped
x = Composite()
x.Foo() # executes Mixin.Foo, perfect
x.Bar() # prints "Base.Foo"
This works because Python executes calls to bound methods of the form
instance.method(argument)
as if they were a call to an unbound method
Class.method(instance, argument)
so making the call in that form gives you the desired result. Inside the methods, self is just the instance that the method was called on, i.e, the implicit first argument (that's explicit as a parameter)
Note however that if a subclass overrides Bar, then there's nothing (good) that you can effectively do about it AFAIK. But that's just the way things work in python.

Categories

Resources