python / python/cpython

Different behavior with mock to same class or different class

Open
#125,348 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

stdlib type-bug
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Bug report

Bug description:
import unittest
from unittest.mock import patch

class Number:
    def __init__(self, value):
        print(f'init: {value}')
        self.value = value

    def get_value(self):
        return self.value

class MockNumber:
    def __init__(self, value):
        print(f'mock init: {value}')
        self.value = value

    def get_value(self):
        return self.value

class TestNumber(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_number(self):
        number = Number(1)
        with patch.object(Number, '__new__', return_value=number):
            test = Number(2)
            print(test.get_value())

        mock_number = MockNumber(1)
        with patch.object(Number, '__new__', return_value=mock_number):
            test = Number(2)
            print(test.get_value())

if __name__ == '__main__':
    unittest.main()

The output is

init: 1
init: 2
2
mock init: 1
1
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

When mock the function new of class Number to return an instance of MockNumber, the behavior is simple: just return the instance of MockNumber.
But when mock the function to return an instance of Number, the function of init will still be called.

CPython versions tested on:

3.11

Operating systems tested on:

Linux

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the supplied unittest and compare patch.object(Number, 'new') when it returns a Number versus a MockNumber. Trace Python's object-construction behavior around new and init, then determine whether the difference is intended; done requires a confirmed behavior and appropriate regression coverage or documentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.