0

Given the following code that attempts to configure the shell_with_tag() to be mocked by `mock_shell_with_tag():

#!/usr/bin/env python3

import pytest

def shell(cmdline, debug=True):
    return f"Original Shell command for {cmdline}.", None

def shell_with_tag(cmdline, debug=True, test_tag=None):
    return shell(cmdline, debug)

def mock_shell_with_tag(cmd, test_tag=None):
    if 'udf delete' in cmd:
        return ['MOCK Record deleted' if test_tag == 'success' else 'Not Found. ', None]
    elif 'udf show' in cmd:
        return ['MOCK Record shown' if test_tag == 'success' else 'Not Found. ', None]
    else:
        raise Exception(f"mock_shell: what function is this {cmd}")

def testUdfs(mocker):
    mocker.patch('tests.mocked.test_mock.shell_with_tag', mock_shell_with_tag)

    def testDelete(name, expected_delete='true'):
        out,err=shell_with_tag(f"udf delete --name {name}", test_tag ='success' if expected_delete else 'failure')
        print(f"Results from UDF delete: {out} err: {err}")
        assert 'MOCK Record' in out, "We went to the real one not the mock"

    testDelete('abc')

Note that the mocked function tests.mocked.test_udfs.shell_with_tag() was found: if it were not then an error message gets generated: it took some effort before getting this correctly.

But when running the testDelete we get the original function invoked instead of the mocked function. What is missing to cause the mock function to activate?

WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560
  • If you are using the function as `shell_with_tag` you will have to patch `shell_with_tag` (without packages and module). – Klaus D. Feb 21 '22 at 09:40
  • @KlausD. That was the first thing attempted but gives `TypeError: Need a valid target to patch. You supplied: 'shell_with_tag'`. I did spend some time and found that the fully qualified as shown was one that did not throw error. – WestCoastProjects Feb 21 '22 at 09:42
  • It also doesn't patch the object if it is imported already. Your example contains the function locally but it sounds like you are importing it. The way you do it might be the problem. Please show us a reproducible example of the TypeError! – Klaus D. Feb 21 '22 at 09:58
  • there is no import. i'll work on an example – WestCoastProjects Feb 21 '22 at 10:27
  • @KlausD reproducible code added – WestCoastProjects Feb 21 '22 at 10:41
  • Throw in a `print(__name__)`. Does it print `tests.mocked.test_mock`? Or does it print `__main__`? Or something else? If it prints anything but `tests.mocked.test_mock`, your patch attempt isn't patching what it needs to patch. – user2357112 Feb 21 '22 at 10:52
  • Also, you forgot to create an exception in `raise(f"mock_shell: what function is this {cmd}")`. You're trying to raise a string. (You'll still get an exception, but it'll be a "why are you trying to raise a string" exception, not the exception you wanted.) – user2357112 Feb 21 '22 at 10:54
  • name is `tests.mocked.test_mock`. . we're apparently good there – WestCoastProjects Feb 21 '22 at 10:56

1 Answers1

0

@KlausD was on the right track by focusing on the imports. The key change to make it work:

    from tests.mocked import test_mock 
    mocker.patch('tests.mocked.test_mock.shell_with_tag', mock_shell_with_tag)

Here is the updated snippet.

#!/usr/bin/env python3

import pytest

def shell(cmdline, debug=True):
    return f"Original Shell command for {cmdline}.", None

def shell_with_tag(cmdline, debug=True, test_tag=None):
    return shell(cmdline, debug)

def mock_shell_with_tag(cmd, test_tag=None):
    if 'udf delete' in cmd:
        return ['MOCK Record deleted' if test_tag == 'success' else 'Not Found. ', None]
    elif 'udf show' in cmd:
        return ['MOCK Record shown' if test_tag == 'success' else 'Not Found. ', None]
    else:
        raise(f"mock_shell: what function is this {cmd}")

def testUdfs(mocker):
    from tests.mocked import test_mock
    mocker.patch('tests.mocked.test_mock.shell_with_tag', mock_shell_with_tag)

    # def testDelete(name, expected_delete='true'):
    # out,err=shell_with_tag(f"udf delete --name {name}", test_tag ='success' if expected_delete else 'failure')
    out,err=test_mock.shell_with_tag(f"udf delete --name abc", test_tag ='success')
    print(f"Results from UDF delete: {out} err: {err}")
    assert 'MOCK Record' in out, "We went to the real one not the mock"

    # testDelete('abc')

print(__name__)

Import resolves to its containing file

WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560