Python Mock Instantiation of Object - python-3.x

Could someone please let me know how to mock the DatabaseAPI object for below unit test case example. Getting error at getURL in test_load.py file.
File load.py
from database_api import DatabaseAPI
Database_api_client = DatabaseAPI(username, password)
def loadFile():
#some code to load the file
File database_api.py
class DatabaseAPI:
def __init__(self, username, password):
self.getUrl()
def getUrl(self):
requests.options(url=SomeURL, headers=request_header)
File test_load.py
import unittest
from load import loadFile
class TestLoad(unittest.TestCase):
def test_loadFile(self):
#some code to test loadfile
But getting get_url connection error. I need to mock the "Database_api_client = DatabaseAPI(username, password)" object
But getting get_url connection error. I need to mock the "Database_api_client = DatabaseAPI(username, password)" object

Related

mock secret manager using pytest

I am trying to mock secret manager. Here is the code which is written for secret manager using boto3 which I am trying to mock and test.
utils.py
import boto3
secret_id = os.environ.get("SECRETS")
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_id)
secrets = json.loads(response['SecretString'])
S3_BUCKET_NAME = secrets["S3_BUCKET_NAME"]
SQS_QUEUE_NAME = secrets["SQS_Queue_Name"]
these variables are then used in different methods.
conftest.py
#pytest.fixture(scope='session', autouse=True)
def secret_manager_resource(aws_credentials):
"""Secret Manager mock client"""
with mock_secretsmanager():
conn = boto3.client("secretsmanager", region_name="us-east-1")
logger.info(f"Secret manager connection {conn}")
yield conn
test_file.py
#contextmanager
def secret_manager_setup(secret_manager_resource):
secret_manager_resource.create_secret(Name="test", SecretString="""{"S3_BUCKET_NAME": "test","SQS_Queue_Name": "test_queue"}""")
yield
class TestSecretManager:
def test_secret_manager(self, secret_manager_resource):
with secret_manager_setup(secret_manager_resource):
try:
result = secret_manager_resource.get_secret_value(SecretId="test")
json_result = json.loads(result['SecretString'])
assert json_result["S3_BUCKET_NAME"] == "test"
assert json_result["SQS_Queue_Name"] == "test_queue"
except Exception as err:
print("Error ---", err)
class TestClass:
def test_some_class(test_var):
from functions.something.some import something
something = someClass({}, param)
When I run pytest it directly goes inside TestClass and calls secret Manager and throws error as it is trying to connect to actual secret manager. Could someone suggest me what can be done to over come this issue?
TestClass is not mocked - so I wouldn't expect that to work. You could use Moto as a class-decorator to ensure everything inside someClass is mocked.
Note that the class-decorator creates a mock around test-methods only, so the code-under-test would have to be inside a test-method for this to work.
#mock_secretsmanager()
class TestClass:
def test_something():
from functions.something.some import something
something = someClass({}, param)
See http://docs.getmoto.org/en/latest/docs/getting_started.html#class-decorator for the documentation and more examples around this.

How to mock a (PyActiveResource) pyactiveresource.connection UnauthorizedAccess response return, using Django TestCase?

I need to create a unit test that mock a REST API failure call, with a side effect of returning an UnauthorizedAccess exception, from the PyActiveResource project (https://github.com/Shopify/pyactiveresource) and store it in the DB. What I've create so far worked and I've got the desired returned side effect. Then, I catch it on the function foo.function_that_call_myfuncion() which looks like this
my_func.py:
from pyactiveresource.connection import UnauthorizedAccess
class MyFuncAnyThing:
...
def function_that_call_myfuncion(self, attr=None):
try:
module.MyTestClass.myfunction(attr)
except UnauthorizedAccess as error:
#Catch the error response object and store it on DB
resp_body = error.response.body
resp_code = error.response.code
#store it on DB
...
And my test file looks like this
unit_test.py:
from pyactiveresource.connection import UnauthorizedAccess
class TestFoo(TestCase):
def test_exception_unauthorized_access(self):
foo = SomeThingFactory()
with patch('module.MyTestClass.myfunction', side_effect=UnauthorizedAccess()):
foo.function_that_call_myfuncion()
#assertions goes below here
...
So, when the execution reached the try block on function_that_call_myfuncion from my_func.py module, the mock function return the desired exception (UnauthorizedAccess) and the object returned looks like this:
error
UnauthorizedAccess('Response(code=None, body="", headers={}, msg="")')
My problems begins when I try to mock the Response body returned on the UnauthorizedAccess exception. This is what I'm doing:
unit_test.py:
from pyactiveresource.connection import UnauthorizedAccess
class TestFoo(TestCase):
def test_exception_unauthorized_access(self):
foo = SomeThingFactory()
bar = MagicMock()
bar.code = 401
bar.body = '{"errors": "Login or wrong password"}'
with patch('module.MyTestClass.myfunction', side_effect=UnauthorizedAccess(bar)):
foo.function_that_call_myfuncion()
#assertions goes below here
...
And that's is how the mocked object looks like:
error
UnauthorizedAccess('Response(code=401, body="<MagicMock name=\'mock.read()\' id=\'2243840764512\'>", headers={}, msg="<MagicMock name=\'mock.msg\' id=\'2243840808464\'>")')
Note that the code attribute on Response is 401, but the body is empty, even though I've set it here bar.body = '{"errors": "Login or wrong password"}'. I also tried to create a Response object and pass it as parameter on the constructor for UnauthorizedAccess class, which is a subclass of
class ConnectionError(Error): of the pyactiveresource.connection lib code (https://github.com/Shopify/pyactiveresource/blob/e609d844ebace603f74bc5f0a67e9eafe7fb25e1/pyactiveresource/connection.py#L34)
unit_test.py:
from pyactiveresource.connection import UnauthorizedAccess, Response
class TestFoo(TestCase):
def test_exception_unauthorized_access(self):
foo = SomeThingFactory()
resp = Response(code=401,body='{"errors": "Login or wrong password"}')
with patch('module.MyTestClass.myfunction', side_effect=UnauthorizedAccess(response=resp)):
foo.function_that_call_myfuncion()
#assertions goes below here
...
But then I got this error from the Class Response:
#classmethod
def from_httpresponse(cls, response):
"""Create a Response object based on an httplib.HTTPResponse object.
Args:
response: An httplib.HTTPResponse object.
Returns:
A Response object.
"""
> return cls(response.code, response.read(),
dict(response.headers), response.msg, response)
E AttributeError: 'Response' object has no attribute 'read'
What am I missing? I just couldn't figure out how to set the 'read' attribute on the constructor, so that I can get the body value.
I'm using Python 3.8, Django 2.2
I managed to mock Shopify's ClientError exceptions by doing something along the lines of:
import urllib.error
from io import BytesIO
import pyactiveresource.testing.http_fake
pyactiveresource.testing.http_fake.initialize()
response = urllib.error.HTTPError('', 401, '', {}, BytesIO(b''))
pyactiveresource.testing.http_fake.TestHandler.set_response(response)
Which I learned about by digging into the Shopify/pyactiveresource tests.

Access a variable from setup_method in pytest

I am quiet new to pytest.
I have declared my Testclass as follows
class TestSerialPort():
#pytest.fixture(autouse=True)
def setupandtear(self,request):
obj = connect_serialport()
yield
obj.close()
def test_abc(self,setupandtear)
print ("object {}".format(obj.port))
I am seeing issue while accessing obj in test method. How can I access "obj" from setup to test_abc?

Using pytest fixtures in class

I have begun writing unit tests for my Flask API. I have gotten them to work when declared outside of a class. However, for simplicity and OOP constraints, I am trying to have everything run from a class. The issue is I cannot seem to pass any fixture methods to my test class. The code I have here is as follow:
#conftest.py
import os, json, pytest
from ..app import create_app
from flask import Flask
#pytest.fixture
def env_setup():
env_name = os.getenv('FLASK_ENV')
app = create_app(env_name)
return app
I am trying to import env_setup into the following file.
# test_BaseURL.py
import pytest
#pytest.mark.usefixtures("env_setup")
class TestStaticPages:
def setUp(self, env_setup):
"""
Setup Test
"""
self.client = env_setup.test_client()
def test_base_route(self, env_setup):
#client = env_setup.test_client()
url = '/'
html1 = b'Welcome to the API. Please visit '
html2 = b'https://example.com to learn more about this app.'
response = self.client.get(url)
assert response.get_data() == html1 + html2
assert response.status_code == 200
I keep geeting the following error when I run this test:
> response = self.client.get(url)
E AttributeError: 'TestStaticPages' object has no attribute 'client'
src/tests/test_BaseURL.py:18: AttributeError
However if I should uncomment the line with client = env_setup.test_client() it works. For whatever reason it cannot seem to grab the setup from the setUP method and keeps erroring out.
Here is how I fixed my issue:
#conftest.py
import os, json, pytest
from ..app import create_app
from flask import Flask
#pytest.fixture
def client():
env_name = os.getenv('FLASK_ENV')
app = create_app(env_name)
client = app.test_client()
return client
I was then able to import the client into my other test class like so.
#test_StaticView.py
import pytest
#pytest.mark.usefixtures("client")
class TestStaticPages:
def test_base_route(self, client):
url = '/'
html1 = b'Welcome to the API. Please visit '
html2 = b'https://example.com to learn more about this app.'
response = client.get(url)
assert response.get_data() == html1 + html2
assert response.status_code == 200

How to Mock a flask-restful class with kwargs

From Intermediate-Usage Flask-RESTful 0.3.7 documentation
in the Passing Constructor Parameters Into Resources section at the bottom, how would you write a test in order to mock kwargs? Side note: I tweaked it so the Smart Engine class is passed directly rather than being instantiated to a variable then passed.
from flask_restful import Resource
class TodoNext(Resource):
def __init__(self, **kwargs):
# smart_engine is a black box dependency
self.smart_engine = kwargs['smart_engine']
def get(self):
return self.smart_engine.next_todo()
You can inject the required dependency into TodoNext like so:
api.add_resource(TodoNext, '/next',
resource_class_kwargs={ 'smart_engine': SmartEngine() })
Test class in question:
import unittest
class TestTodoNext(unittest.TestCase):
todo_next_instance = TodoNext() # How would you mock smart_engine in this case?
You can use Mock object from unittest.mock to mock smart_engine.
import unittest
from unittest.mock import Mock
class TestTodoNext(unittest.TestCase):
smart_engine = Mock()
smart_engine.next_todo.return_value = "YOUR DESIRED RETURN VALUE"
todo_next_instance = TodoNext(smart_engine=smart_engine)
self.assertEqual(todo_next_instace.get(), "YOUR DESIRED RETURN VALUE")

Resources