1

I want to mock a function call in the body of the surrounding function which I'm testing. I need to do this with flexmock or at least know if it's not possible. Take the following piece of code as an example. I have 3 files. utils.py with a single function run_command and an api.py with a class that has a single method, the test_api.py. All of this is for demonstration purposes and isn't particularly useful but should be able to describe my problem

# util.py
import subprocess

def run_command(cmd):
    return subprocess.check_output(cmd)

Now api.py will maake use of run_command from util.py

# api.py
from util import run_comand


class Api:

    def get_update(self):
        result = run_command(["pwd"]).decode("utf-8")
        return f"Update: {result}"

Now I want to write a test for Api.get_update but I don't want to actually execute run_command

using the mock module, I would have written the test like

# test_api.py
from unittest import mock

@mock.patch("api.run_command")
def test_get_update(run_command_mock):
    run_command_mock.return_value = b"sucess!!!"
    api = Api()
    result = api.get_update()
    assert result == "Update: success!!!"

The above test works as expected. It doesn't actually execute run_command when get_update is called. It uses the mocked version. Now I want to do this with flexmock. I don't know if this is possible though. Just that I'm contributing to a project and all tests are built with flexmock so I want to follow the same pattern. Unfortunately,I couldn't find a test that solves a similar problem. From this SO mocking-functions-with-flexmock-in-python, I came up with this

import utils as utils_module
import flexmock
from api import Api

def test_get_update():
    flexmock(utils_module).should_receive("run_command").with_args(["pwd"]).once().and_return("success!!")
    api = Api()
    result = api.get_update()
    assert result == "Update: success!!!"

The above test fails. run_command from utils is still executed not my mocked version. How do I fix this using flexmock?

1 Answers1

0

I figured out what I was doing wrong. I was mocking run_command from where it's coming from instead of where it's been used like I did with @mock.patch. To fix it, I had to rewrite my test like this

import flexmock import flexmock
import api as api_module # Instead of importing utils, I'm importing api since that's where run_command is called even though it's coming from utils


def test_get_update():
    flexmock(api_module).should_receive("run_command").once().and_return(b"success!!!")
    api = api_module.Api()
    result = api.get_update()
    assert result == "Update: success!!!"