简体   繁体   中英

Mock method of an object inside function [python]

I have two files:- file1.py and file2.py

file2.py has following code:-

import json

def fun1():
    s = "{'function1': 'val1'}"
    s = json.dumps(s)
    print("in fun1 ", s)
    return s

def fun2():
    s = "{'function2': 'value2'}"
    s = json.dumps(s)
    print("in fun2 ", s)
    return s

def fun5():
    fun2()
    return fun1()

file1.py has following code

from mockito import when, unstub
from file2 import fun5

def mock_the_function():
    when("file2.fun1.json").dumps(...).thenReturn("something something")
    print(fun5())
    unstub()

I want to mock "dumps" inside "fun1" only, not "fun2". Code which I have written is showing error. I don't want to do it by parameter comparison. Is there any other way I can have a function being passed inside "when"?

First a quick note:

  • json.dumps takes an object, not a string, so it's kind of redundant to to call it as you are inside fun1 and fun2 . Perhaps you're looking for json.loads ?

Next I'd consider some different approaches:

  • When you mock json.dumps , you want to mock the the json property of the file2 module, so it would just be when("file2.json")... in the setup code for your test.

  • Because (as above), we're mocking the json module globally in the file2 module, it's not possible to, as you asked, in that context of a single test, mock json.dumps inside of fun1 but not fun2 , but what I'd suggest is to simply have two tests, and unstub in a tear down method. For example:

from unittest import TestCase

class TestExample(TestCase):
    def tearDown(self):
        unstub()

    def test_fun1(self):
        when("file2.json").dumps(...).thenReturn("something something")
        # in this invocation json is stubbed
        self.assertEqual(fun1(), "something something")

    def test_fun2(self):
        # but now unstub has been called so it won't be stubbed anymore.
        self.assertEqual(fun2(), "...output of fun2...")

Another alternative is for fun1 and fun2 to take a function that will do the work that the global json module is currently doing. This use of the Dependency Inversion Principle makes the code more testable, and means you don't even need mockito in your tests. For example:

def fun1(json_decoder):
   s = "..."
   return json_decoder(s)

# ....
from unittest.mock import MagicMock

def test_fun_1():
   mock_decoder = MagicMock()
   mock_decoder.return_value = "asdf"
   assert fun1(mock_decoder) == "asdf"

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