2

I need to fake the return value of sys.stdout.istty() in a test case. Monkeypatching with monkeypatch.setattr("sys.stdout.isatty", lambda: True) is no option because it conflicts with pytest stdout capturing when using option -s. How can I fake on the test case level?

thinwybk
  • 4,193
  • 2
  • 40
  • 76

2 Answers2

2

Python does not allow monkey-patching built-in types such as file.. sys.stdout is a file object. The patch has to be applied in the production code module namespace (<module>.sys.stdout). When using pytest-mock (fixture mocker) this looks as follows:

def test_of_prod_code_with_dependency(mocker):
    stdout_mock = mocker.patch("<module>.sys.stdout")
    stdout_mock.isatty.return_value = istty

    # production code which depends on sys.stdout.isatty() comes here
thinwybk
  • 4,193
  • 2
  • 40
  • 76
0

Using monkeypatch of pytest

To use a lambda as a function, you need to parenthesize it.

import pytest

def test_stdout_istty(monkeypatch):
    # To use a lambda as a function, you need to parenthesize it.
    monkeypatch.setattr("sys.stdout.isatty", (lambda: True))
    #                                        ^            ^
    assert sys.stdout.isatty() == True
    assert sys.stdout.isatty() == False

Using a unittest mock

import pytest
from unittest import mock

def test_stdout_istty():
    with mock.patch('sys.stdout') as stdout:
        stdout.isatty.return_value = False
        assert sys.stdout.isatty() == False
        assert sys.stdout.isatty() == True
        # if your code contains stdout.isatty, 
        # then put inside of the context manager. 

Constantin Hong
  • 701
  • 1
  • 2
  • 16