Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pytest - Patching a class does not work, calls class instead

Not sure why but here is my code snippet :

stats_collector.py

class StatsCollector( object ) :
def __init__( self, user_id, app_id ) :
    logging.info( "Stats: APP_ID = {0}, ID = {1}".format( app_id, user_id ) )

mydb.py

from namespacename.mylibname.stats_collector import StatsCollector
class Db( object ) :
    # constructor/destructor
    def __init__( self, dbname ) :
        ....

    def beginTransaction( self, user_id, app_id ) :
        logging.info( "Begin" )
        self._stats = StatsCollector( user_id, app_id ) 

test_mylibname_mydb

from namespacename.mylibname.mydb import Db
from namespacename.mylibname.stats_collector import StatsCollector
@pytest.mark.mydb_temp
@mock.patch( 'namespacename.mylibname.stats_collector.StatsCollector')
def test_db_beginTransaction( mock_stats_collector ) :
    db = Db( TEST_DB_NAME )
    mock_stats_collector.return_value = mock.Mock()
    db.beginTransaction( TEST_ID, TEST_APP_ID )
    ......
    ......

I can see my log in my stats_collector.__init__ - why do I enter that? Shouldn't when inside my beginTransaction I call StatsCollector return value to be a MockObject and I shouldn't see any logs ?

Structure looks like :

tests/
├── mylibname
│   ├── test_mylibname_mydb.py
namespacename/mylibname
├── stats_collector
│   ├── mylibname_stats_collector.py
│   ├── __init__.py
├── mydb
│   ├── mylibname_mydb.py
│   ├── __init__.py

** Edit **

Followed advice on comment -

@mock.patch( 'namespacename.mylibname.mydb.StatsCollector')
def test_db_beginTransaction( mock_stats_init ) :
    db = Db( TEST_DB_NAME )
    db.beginTransaction( TEST_UUID, TEST_APP_ID )
    print db._transaction
    assert db._transaction is mock_stats_init

gets me :

E       AssertionError: assert <namespacename.mylibname.stats_collector.mylibname_stats_collector.StatsCollector object at 0x7f42d837b110> is <MagicMock name='StatsCollector' id='139925072008976'>
E        +  where <namespacename.mylibname.stats_collector.mylibname_stats_collector.StatsCollector object at 0x7f42d837b110> = <namespacename.mylibname.mydb.mylibname_mydb.Db object at 0x7f42d8365850>._transaction
like image 481
ghostrider Avatar asked Oct 23 '25 10:10

ghostrider


2 Answers

You need to patch The symbol 'A' in the module which is being tested i.e. 'B'.

When you do @mock.patch("full.path.A"), it should be:

@mock.patch("full.path.to.B.A")

Now the symbol A in module B is patched with your mock.

like image 62
rdas Avatar answered Oct 25 '25 23:10

rdas


Aren't you missing the name of the file itself?

@mock.patch( 'namespacename.mylibname.stats_collector.mylibname_stats_collector.StatsCollector')
like image 27
Higor Rossato Avatar answered Oct 25 '25 23:10

Higor Rossato



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!