How to properly mock subprocess.check_output()?

Issue

This Content is from Stack Overflow. Question asked by Thops

I’m utesting float(self) that is supposed to get downloadable file size from yt-dlp.

To call yt-dlp I’m using subprocess.check_output().
I’d like to mock it (subprocess.check_output) but can’t find the way how.

Please help.

Tried approaches:

First one doesn’t work at all. It always reads 0.0.
Second one brings this traceback (Attribute Error):

    Error
Traceback (most recent call last):
  File "/usr/lib/python3.10/unittest/mock.py", line 1369, in patched
    return func(*newargs, **newkeywargs)
  File "/home/elphael/PycharmProjects/hoarder/core/test_file.py", line 61, in test__float__handlesSpecialCode
    self.assertAlmostEqual(15.83, float(obj))  # verify it returns value
  File "/home/elphael/PycharmProjects/hoarder/core/file.py", line 40, in __float__
    bytesize = subprocess.check_output(f"yt-dlp -O filesize_approx {self.url}".split(),
  File "/usr/lib/python3.10/subprocess.py", line 420, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.10/subprocess.py", line 501, in run
    with Popen(*popenargs, **kwargs) as process:
AttributeError: __enter__

I’ve tried to mock __enter __ but to no avail.

FUNCTION

  1. grab self.url and poll yt-dlp
  2. convert bytes to Mb (auxillary.bytesto())
  3. assign result to self.length and return
    def __float__(self):

        try:
            bytesize = subprocess.check_output(f"yt-dlp -O filesize_approx {self.url}".split(),
                                               stderr=subprocess.STDOUT)
            megabytes = auxillary.bytesto(bytesize, 'm')  # I only need approx size
            self.length = round(megabytes, 2)
        except subprocess.CalledProcessError:
            return -2.0
        return self.length

UTEST

  1. init a class that calls float(self)
  2. verify self.length = expected
@patch("subprocess.Popen")
    def test__float__handlesSpecialCode(self, mock_subproc_popen):
        """
            -1.0 length is meant to show that length is yet to be calculated
        """
        process_mock = Mock()
        attrs = {"communicate.return_value": ("output", "error")}
        process_mock.configure_mock(**attrs)
        mock_subproc_popen.return_value = process_mock
        obj = TFile("https://www.youtube.com/watch?v=GtL1huin9EE", -1.0)
        self.assertAlmostEqual(15.83, float(obj))  # verify it returns value
        self.assertNotEqual(-1, obj.length)  # verify self.length preserves that value

Any input is deeply appreciated.



Solution

This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.

This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?