How to fake Popen in test?

落花浮王杯 提交于 2021-01-29 05:51:03

问题


I've successfully Faked other module with my own Fake implementation or using monkeypatch. But in this case using both fake implementation or monkeypatch failed for subprocess.Popen:

  • Using monkeypatch, failed. The result still the real opened windows title, not "foo".
class TestController:

    def test_get_all_windows(self, ctrl_fixture, monkeypatch):

        def fake_communicate(a):
            return "foo"

        monkeypatch.setattr(subprocess.Popen, 'communicate', fake_communicate)
        output = ctrl_fixture.get_all_windows()
        print(output)

  • Using faking also failed, I've tried to mimic the original but it still failed. The result of output still the real windows titles, not "foo"
class FakePopen(object):
    def __init__(self, args, stdout=None):
        super().__init__()      
        self.args = args
        self.stdout = stdout

    def communicate(self):
        return "foo"

class TestController:
    def test_get_all_windows(self, ctrl_fixture, monkeypatch, mocker):

        def fake_communicate(a):
            return "foo"
        subprocess.Popen = FakePopen
        subprocess.Popen.communicate = fake_communicate
        output = ctrl_fixture.get_all_windows()
        print(output)

my function is:

    def get_all_windows(self):
        all_windows = ""
        all_windows_proc = Popen(["wmctrl", "-l"], stdout=PIPE)
        all_windows_dirty, err = all_windows_proc.communicate()
        for line in all_windows_dirty.splitlines():
            windows_name = line.split(None, 3)[-1].decode()
            all_windows += "{}\n".format(windows_name)
        return all_windows

The test above using print instead of assert cause I still want to check the output.

Thanks in advance.

Update solution

According to munk comments. Great thanks to him.

both solution worked:

def test_get_all_windows_one(self, ctrl, monkeypatch):

    window_title = b"0x006000ab  0 machine-name foo_window_title"

    def fake_communicate(a):
        return window_title, "err"

    Lupr.controllers.controller.Popen = FakePopen
    Lupr.controllers.controller.Popen.communicate = fake_communicate

    output = ctrl.get_all_windows()
    assert output == "foo_window_title\n"

def test_get_all_windows_two(self, ctrl, monkeypatch):

    window_title = b"0x006000ab  0 machine-name foo_window_title"

    def fake_communicate(a):
        return window_title, "err"

    monkeypatch.setattr(Lupr.controllers.controller, "Popen", FakePopen)
    monkeypatch.setattr(
        Lupr.controllers.controller.Popen, "communicate", fake_communicate
    )
    output = ctrl.get_all_windows()
    assert output == "foo_window_title\n"


回答1:


You're patching subprocess.Popen, but in your function under test you're using Popen directly. You're changing the wrong symbol table.

If your function is in foo.py, you want to patch foo.Popen or change your function to use subprocess.Popen.



来源:https://stackoverflow.com/questions/56043143/how-to-fake-popen-in-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!