mocking smbclient call that yields a json result [duplicate]

3 weeks ago 15
ARTICLE AD BOX

You are setting the wrong mock: mock_tmp is not the context manager, but instead returns a context manager. Replace your setup line with:

mock_tmp.return_value.__enter__.return_value.name = mytmpname

and your test will work.

Nathaniel Ford's user avatar

Nathaniel Ford

21.3k20 gold badges98 silver badges112 bronze badges

answered Mar 4, 2015 at 10:27

Michele d'Amico's user avatar

To expand on Nathaniel's answer, this code block

with tempfile.NamedTemporaryFile() as mytmp: return mytmp.name

effectively does three things

# Firstly, it calls NamedTemporaryFile, to create a new instance of the class. context_manager = tempfile.NamedTemporaryFile() # Secondly, it calls __enter__ on the context manager instance. mytmp = context_manager.__enter__() # Thirdly, we are now "inside" the context and can do some work. return mytmp.name

When you replace tempfile.NamedTemporaryFile with an instance of Mock or MagicMock

context_manager = mock_tmp() # This first line, above, will call mock_tmp(). # Therefore we need to set the return_value with # mock_tmp.return_value mytmp = context_manager.__enter__() # This will call mock_tmp.return_value.__enter__() so we need to set # mock_tmp.return_value.__enter__.return_value return mytmp.name # This will access mock_tmp.return_value.__enter__.return_value.name

answered Nov 30, 2020 at 12:56

FiddleStix's user avatar

2 Comments

This answer was perfectly succinct and helped me out. Thank you. I was using a contextlib.asynccontextmanager and the only thing I needed to change to get this to work was changing __enter__ to __aenter__

2023-04-24T18:56:20.743Z+00:00

2024-02-21T16:17:18.493Z+00:00

Extending Peter K's answer using pytest and the mocker fixture.

def myfunc(): with tempfile.NamedTemporaryFile(prefix='fileprefix') as fh: return fh.name def test_myfunc(mocker): mocker.patch('tempfile.NamedTemporaryFile').return_value.__enter__.return_value.name = 'tempfilename' assert myfunc() == 'tempfilename'

answered Oct 9, 2019 at 18:56

mobrienv's user avatar

Here is an alternative with pytest and mocker fixture, which is a common practice as well:

def test_myfunc(mocker): mock_tempfile = mocker.MagicMock(name='tempfile') mocker.patch(__name__ + '.tempfile', new=mock_tempfile) mytmpname = 'abcde' mock_tempfile.NamedTemporaryFile.return_value.__enter__.return_value.name = mytmpname assert myfunc() == mytmpname

answered Aug 7, 2019 at 13:18

Peter K's user avatar

I extended hmobrienv's answer to a small working program

import tempfile import pytest def myfunc(): with tempfile.NamedTemporaryFile(prefix="fileprefix") as fh: return fh.name def test_myfunc(mocker): mocker.patch("tempfile.NamedTemporaryFile").return_value.__enter__.return_value.name = "tempfilename" assert myfunc() == "tempfilename" if __name__ == "__main__": pytest.main(args=[__file__])

answered Jan 13, 2021 at 0:07

David Howlett's user avatar

1 Comment

It's crazy how most of the answers here explain the same thing but yours was the only one that could make me understand it. haha

2023-09-26T20:39:42.043Z+00:00

Another possibility is to use a factory to create an object that implements the context manager interface:

import unittest import unittest.mock import tempfile def myfunc(): with tempfile.NamedTemporaryFile() as mytmp: return mytmp.name def mock_named_temporary_file(tmpname): class MockNamedTemporaryFile(object): def __init__(self, *args, **kwargs): self.name = tmpname def __enter__(self): return self def __exit__(self, type, value, traceback): pass return MockNamedTemporaryFile() class TestMock(unittest.TestCase): @unittest.mock.patch("tempfile.NamedTemporaryFile") def test_cm(self, mock_tmp): mytmpname = "abcde" mock_tmp.return_value = mock_named_temporary_file(mytmpname) self.assertEqual(myfunc(), mytmpname)

answered Feb 4, 2022 at 20:13

user18122828's user avatar

1 Comment

This is the only working solution for my case. Thanks !

2023-04-06T15:11:01.53Z+00:00

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Read Entire Article