简体   繁体   中英

How to fake Popen in test?

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"

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM