Reputation: 1695
I have a class something like this.
class Upgrade:
def __init__(self, ssh_client):
self.ssh_client = ssh_client
self.channel = self.ssh_client.invoke_shell(width=1000, height=1000)
self.stdin = self.channel.makefile('wb')
self.stdout = self.channel.makefile('r')
def do_upgrade(self):
# execute some commands on paramiko channel
for line in self.stdout:
if str(line).startswith("PLAY RECAP"):
# do something
When I trying to mock self attribute called 'stdout' like this(using pytest),
def return_stdout(*args, **kwargs):
stdout = "\n\rSome return value\n\r"
return stdout
monkeypatch.setattr(Upgrade, 'stdout', return_stdout)
I'm getting following error.
> monkeypatch.setattr(Upgrade, 'stdout', return_stdout)
E AttributeError: <class 'Upgrade'> has no attribute 'stdout'
Then, How can I mock 'stdout' using pytest or pytest-mock?
Upvotes: 3
Views: 2572
Reputation: 9359
the class does not have the attribute, you're setting stdout
as an instance variable. And even if you'd mock it, you'd overwrite it in the constructor (self.stdout = self.channel.makefile('r')
). Create a wrapper/property, and monkeypatch that instead:
class Upgrade:
def __init__(self, ssh_client):
self._stdout = self.channel.makefile('r')
def get_stdout(self):
return self._stdout
then in the test mock the encapsulating method instead:
monkeypatch.setattr(Upgrade, 'get_stdout', return_stdout)
Upvotes: 4