Search code examples
pythonpython-mockpython-typing

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


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?


Solution

  • 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.