curtank
curtank

Reputation: 700

How to replace a class?

I am writing test files for a Python module

class A:
    def func(self):
        B().sub_func()
class B:
    def sub_func(self):
        pass

and I need block B's side effect while testing A. my question is that how to replace class B in test file.

class ATest(unittest.TestCase):
    def test_a(self):
        a=A()
        a.func()
        #now object a will invoke a func that B is a mock class

following the instruction of accepted answer. I finish my tests

tws/main.py

class A(object):
    def func(self):
        b=B()
        print('func ')
        b.sub_func()
class B(object):
    def sub_func(self):
        print('real sub')
        c=C()
        c.c_sub_func()
class C(object):
    def c_sub_func(self):
        print('c')

test/test_mock.py

import unittest
from unittest.mock import patch
from tws.main import A
class B():
    def sub_func(self):
        print('mock')
        return 12
class TestMock(unittest.TestCase):
    @patch('tws.main.B',new=B)
    def test_af(self):
        a=A()
        print(a.__dict__)
        a.func()
        print('rrr')

it will print mock,hope it will help other people with same problems.

Upvotes: 1

Views: 3900

Answers (1)

Will Keeling
Will Keeling

Reputation: 23004

As suggested in the comments, you can mock out class B by using unittest.mock - in particular patch().

You can use patch() as a decorator on your test method, making sure you add an extra argument to receive the mocked class B:

from unittest.mock import patch

class ATest(unittest.TestCase):

    @patch('package.module.B')
    def test_a(self, mock_b):  # mock_b will hold the mocked class B
        a = A()
        a.func()

Note that the path you pass to the decorator must be the path to where B is used (the same module containing class A) not the path to where class B is defined. See Where to patch for more info on that.

Upvotes: 3

Related Questions