How to mock a Python class during testing for runtime typing checks?

Viewed 216

I have some application method that uses the @typeguard.typechecked decorator for performing runtime checks of the passed parameters:

class SalesDeal:
    pass

@typechecked
def do_something(deal: SalesDeal):
   pass

Inside a test I have fake class FakeSalesDeal which implements a minimal mock for SalesDeal (which is a very complicated class in reality):

class FakeSalesDeal:
    pass


def test_foo():
    deal = FakeSalesDeal()
    do_something(deal)

This test will of course fail because the @typechecked decorator will raise an error due to a different class.

Is there a way to mock/fake the class of FakeSalesDeal in order make the test pass?

2 Answers

You can use MagicMock with spec set to SalesDeal instead of creating a fake class.

isinstance(mock, SalesDeal) will be True for that mock object & you should be able to bypass the typecheck.

from unittest.mock import MagicMock

# ...

def test_foo():
    deal = MagicMock(spec=SalesDeal)
    print(isinstance(deal, SalesDeal))
    do_something(deal)

test_foo()

This prints:

True

& doesn't throw any type check error.

This works because typechecked explicitly checks for Mock objects being passed with:

    if expected_type is Any or isinstance(value, Mock):
        return

Code from here

So if you use proper mocks, typechecked should not be causing any issues for you.

My final solution:

class FakeSalesDeal(MagicMock):
    pass
Related