We are deploying the code in CI/CD
fashion via Terraform
. So, we have a lambda
function
under which I have written a code for retrieving the specific secret
creds.
Below is my lambda code:
logger = get_provisioner_logger()
session = boto3.session.Session()
client = session.client(
service_name="secretsmanager",
region_name=""
)
def lambda_handler(event, context):
logger.info("lambda invoked with event: " str(event))
domain_name = "db-creds"
secret_data = getCredentials(domain_name)
acc = secret_data["acc"]
user = secret_data["user"]
password = secret_data["pass"]
#....
#here we are invoking other methods where we are passing the above creds
#....
return handler.handle(event)
def getCredentials(domain_name):
try:
response = client.get_secret_value(SecretId=domain_name)
result = json.loads(response['SecretString'])
print(result)
logger.info("Got value for secret %s.", domain_name)
return result
except UnableToRetrieveDetails as e:
logger.error("unable to retrieve secret details due to ", str(e))
raise e
Now, I have written a test case where I am trying to mock the client and trying to fake the return value of the response but am unable to do so. Below is my code:
from unittest import TestCase
from unittest.mock import patch
from api.lambda_handler import getCredentials
import json
@patch('api.lambda_handler.client')
class TestSecretManagerMethod(TestCase):
def test_get_secret_creds(self, sm):
sm.response.return_value = {"secret":"gotsomecreds"}
actual = getCredentials("db-creds")
self.assertEqual(actual, "hey")
It gives me below error:
raise TypeError(f'the JSON object must be str, bytes or bytearray, '
TypeError: the JSON object must be str, bytes or bytearray, not MagicMock.
What exactly am I missing here?
CodePudding user response:
Kevin's answer is on the right track.
The problem is that you're mixing up what needs to be patched and returned.
In your code you're saying: If you call client.response()
then return {"secret":"gotsomecreds"}
. The problem is that this is not what's happening in your code.
You're actually calling client.get_secret_value(something)
and that's what needs to be patched:
@patch('api.lambda_handler.client')
class TestSecretManagerMethod(unittest.TestCase):
def test_get_secret_creds(self, sm):
sm.get_secret_value.return_value = {
"SecretString": '{"secret": "gotsomecreds"}',
}
actual = getCredentials("db-creds")
self.assertEqual(actual, {"secret": "gotsomecreds"})
I also took the liberty of fixing the assertion, because the way you set it up "hey"
won't be returned.
As an aside, I highly recommend you check out the moto project. It provides mocks around most of the AWS API and will save you a lot of work.