robertokl
robertokl

Reputation: 1909

How to mock a class in Python?

I'm new to Python, but I used to work with ruby.

I'm trying to do some tests with Python but I can't figure out how I mock a class for my test.

Let's say I have this real class:

from database import DB
class Foo:
  def do_it(self):
    x = {'key': 'value'}
    DB.save(x)
    # do other stuff with x
    return x

Now, I want to test if everything I'm doing with x returns me the right result, and I want to test if DB.save was called with x as parameter, but I don't want to actually save x to database. To see if DB.save is being called, I can use some mock framework, but how can I tell Foo class that I need it to use the mock object and not the real DB object?

Thank You.

EDIT: Sorry, my example wasn't enough for what I need to accomplish.

Let's see this new example:

from database import DB
class Foo:
  DB.connect()
  def do_it(self):
    x = {'key': 'value'}
    DB.save(x)
    # do other stuff with x
    return x

And for instance, let's say the database is down.

When I import Foo, it raises the connection error and I do not have time to mock DB.

What should I do??

Upvotes: 2

Views: 2202

Answers (2)

Daniel Roseman
Daniel Roseman

Reputation: 599590

The answer is, don't write your classes like that. It's a strange way to do so anyway - there shouldn't really be any executable code at the class level, other than attribute and method definitions. You should setup the connection in the __init__ method.

class Foo(object):
    def __init__(self, *args, **kwargs):
        DB.connect()

Upvotes: 7

Sven Marnach
Sven Marnach

Reputation: 601589

DB will be looked up in the module's scope everytime Foo.do_it() gets called. You can simply assign a different object to DB and it will be used. If your class Foo is in some module foo, you can do something like

import foo
foo.DB = mocked_DB
f = foo.Foo()
f.do_it()

Upvotes: 6

Related Questions