I'm starting to learn Python, and along with that, I try learn how to write tests for my code. I've decided to use py.test and mock for that. I'm given a quite big and complex class, to write tests for, so for a start I decided to work on a simpler example of my own.
So, I've written a very simple class (person.py
in a package called src_pkg
)
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
def can_do_it(self, x):
result = True if x > 5 else False
print "result: ", result
return result
What I want to do, is mock the Person class, and create an instance of the mocked class, in order to be able to call the can_do_it()
method.
The reason I want to do that, is because the real class I'm working on, has a really complex constructor, and I don't want to make an instance of the class by writing something like foo = Foo(x, y, z)
So, I've written my test code (test_person.py
in a package called test_pkg
), which is the following:
from mock import patch
class TestPerson():
def test_can_do_it(self):
with patch('src_pck.person.Person') as Person:
person = Person.return_value
print "can he do it? :", person.can_do_it(4)
but when I run:
$ py.test -v -s test_person.py
I get the following result:
platform linux2 -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2 -- /home/kostas/.virtualenvs/excite/bin/python
collected 1 items
test_person.py:5: TestPerson.test_can_do_it Can he do it? : <MagicMock name='Person().can_do_it()' id='37709904'>
PASSED
I would expect that the expression print "can he do it? :", person.can_do_it(4)
would result to can he do it? : False
. As a result, there is no point of asserting anything.
I think that when I run the test, it does not call the can_do_it()
method at all! (otherwise the print statement of the method would be printed, right?)
So, what am I doing wrong?
Any help would be really appreciated.
Thank you in advance.
A mock object has mock methods, not the real methods. The real methods may depend on having a real, fully-constructed object of the right class as self
, which a mock object can't provide. If you need to test the can_do_it
method, you can't use a mock Person
to do it.
If can_do_it
doesn't depend on having a fully-constructed self
available, you can move the implementation to a module-level function or static method and have the instance method call that:
class Person(object):
...
def can_do_it(self, x):
return _can_do_it(x)
def _can_do_it(x):
result = True if x > 5 else False
print "result: ", result
return result
Then you can just test the module-level function. If you need certain bits and pieces of a Person
, but you don't need to construct the whole thing, then you can just construct (or mock) the bits and pieces and have the module-level function take them as arguments.
If can_do_it
depends on having a real self
or most of one, you may need to construct a real Person
object and call the method.
Patch the __init__
method using mock.patch.object
:
from mock import patch
import src_pkg.person as p
class TestPerson():
def test_can_do_it(self):
with patch.object(p.Person, '__init__', lambda self: None):
person = p.Person()
print "can he do it? :", person.can_do_it(4)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With