1

It seems that the kwarg assignment is not getting mocked in the mock.patch, but if it's called inside a function, it is.

Any ideas?

import platform
import mock


def test(arch=platform.machine()):
    print "arch = %s" % arch
    print "machine = %s" % platform.machine()

with mock.patch.object(platform, "machine", return_value="TEST"):
    test()


# This outputs
# arch = x86_64
# machine = TEST
Hemna
  • 13
  • 2
  • Does this answer your question? [How can i check call arguments if they will change with unittest.mock](https://stackoverflow.com/questions/16236870/how-can-i-check-call-arguments-if-they-will-change-with-unittest-mock) – AXO Jul 04 '20 at 16:21

1 Answers1

1

Function defaults are set and stored with the function object when the function definition is executed.

Mocking platform.machine works fine, but the default value for the arch argument has long since been set by calling platform.machine() and using the return value. The expression is not used when test() is called.

See "Least Astonishment" in Python: The Mutable Default Argument for why that is.

You'll need to patch platform before you ever import the module that defines the function; you could move the function to a new module, and do this:

import sys

if 'modulename' in sys.modules:
    del sys.modules['modulename']  # ensure the cached module is cleared

with mock.patch.object(platform, "machine", return_value="TEST"):
    from modulename import sys
    test()

del sys.modules['modulename']  # clear the module with the mocked value again

This is rather cumbersome and will fail if you were to run tests in threads.

You can use None as the default instead and create the default when test is called instead:

def test(arch=None):
    if arch is None:
        arch = platform.machine()
    print "arch = %s" % arch
    print "machine = %s" % platform.machine()
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343