简体   繁体   中英

Mock function called on import

I have a module I need to test that calls a function on import but I cannot call this function for various reasons. So I am mocking this function but even mocking it calls import.

For example I am testing mod1.py that looks like this:

import os

def bar():
    return 'foo'

def dont_call():
    os.listdir("C:\\tmp")

dont_call()

And my test looks something like this:

import mock

@mock.patch("mod1.dont_call")
def test_mod1(mock_dont_call):
    import mod1
    assert mod1.bar()=='foo'

if __name__=="__main__":
    test_mod1()

The problem is os.listdir is called.

I cannot change mod1 so what can I do?

I am using python2.7.

To put this in context I am testing a module that opens a database connection on import which I do not agree with but I can see the reasoning behind it. Unfortunately I cannot access this database on my QA machine.

If you want code to 'not' be executed on import put them inside the following condition:

In mod1.py, do the following:

if __name__=="__main__":
    dont_call()

This is because, by default when you import a python module, all the code in it gets executed. By adding the above condition, you are explicitly stating that dont_call() is to be called only when the file it run as a script and not when it is imported in other modules.

The workaround I found was to mock what dont_call was calling giving me something like this:

import mock

@mock.patch("os.listdir")
def test_mod1(mock_dont_call):
    import mod1
    assert mod1.bar()=='foo'

if __name__=="__main__":
    test_mod1()

Check your dir

$tree.
test_shot/
├── mod1.py
├── __pycache__
│   └── mod1.cpython-310.pyc
└── test.py

Below code works fine for me.

mod1.py
import os

def bar():
    return 'foo'

def dont_call():
    os.listdir(".")

def call_this():
    print('called this')

call_this()
dont_call()

test.py

import mock

@mock.patch("mod1.dont_call")
def test_mod1(mock_dont_call):
    import mod1
    assert mod1.bar()=='foo'

if __name__=="__main__":
    test_mod1()

Here is output:

$cd test_shot
$python3 test.py
called this

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM