I have two python files, the first python file which is triggered in server will dynamically fetch the variable result based on the environment the script is triggered . for an example
for this example, when python script is triggered in dev environment . ideally, ${RPM_ENVIRONMENT} will return as 'DEV'
inside my conf.py file i have below script
import os
import json
import subprocess
import logging
from os import listdir
from os.path import isfile, join
_ENV = os.popen("echo ${RPM_ENVIRONMENT}").read().split('\n')[0]
SERVER_URL = {
'DEV':{'ENV_URL':'https://dev.net'},
'UAT':{'ENV_URL':'https://uat.net'},
'PROD':{'ENV_URL':'https://prod.net'}
}[_ENV]
inside my test cases script , i wanted to mimic as dev environment using unitest mock . i have tried below script but it was returning RPM_ENVIROMENT as key error .
test_env.py
import unittest , sys , tempfile, os , json , shutil
from unittest import mock
with mock.patch.object(os, 'popen') as mock_popen:
sys.path.insert(1, 'C:/home/test/conf')
import env_test as conf
I have tried using os.popen to mimic , but i am confused on how i can assign 'DEV' to _ENV variable .
when i tried to run this script, it was returning error as
SERVER_URL = {
KeyError: <MagicMock name='popen().read().split().__getitem__()' id='1893950325424'
CodePudding user response:
I didn't quite understand if your code is inside a function or not. If it is, the best way to do so is not patch.object. It's just a normal patch:
Consider this example:
def question():
return os.popen("what_ever").read()
def test_question():
with patch("os.popen") as popen_mock:
popen_mock().read.return_value = "DEV"
actual = question()
assert actual == "DEV"
In my opinion, patching os.popen and adding read to it's structure is the best practice.
Good luck !
CodePudding user response:
When you mock popen
it will return a MagickMock
object and that object does not have a defined read
response. You need to define what happens when someone calls read()
on a MagickMock
object that you have returned. Although it is not the most elegant solution, you can do this by adding this line in the with
block:
mock_popen.return_value.read.return_value = "DEV"
This will instruct the MagickMock
object to return the string "DEV" when read()
is called on it.