How to test render_to_response in Pyramid Python - python

I have a piece of code that calls Pyramid's render_to_response. I am not quite sure how to test that piece. In my test, the request object that is sent in is a DummyRequest by Pyramid. How can I capture to_be_rendered.
from pyramid.renderers import render_to_response
def custom_adapter(response):
data = {
'message': response.message
}
to_be_rendered = render_to_response(response.renderer, data)
to_be_rendered.status_int = response.status_code
return to_be_rendered

I believe render_to_response should return a response object. You should be able to call custom_adapter directly in your unit test, providing a DummyRequest and make assertions on the Response object returned by your custom_adapter
def test_custom_adapter(self):
dummy = DummyRequest() # not sure of the object here
response = custom_adapter(dummy)
self.assertEqual(response.status, 200)

Related

How to mock client object

I am working on writing unittest for my fastapi project.
One endpoint includes getting a serviceNow ticket. Here is the code i want to test:
from aiosnow.models.table.declared import IncidentModel as Incident
from fastapi import APIRouter
router = APIRouter()
#router.post("/get_ticket")
async def snow_get_ticket(req: DialogflowRequest):
"""Retrieves the status of the ticket in the parameter."""
client = create_snow_client(
SNOW_TEST_CONFIG.servicenow_url, SNOW_TEST_CONFIG.user, SNOW_TEST_CONFIG.pwd
)
params: dict = req.sessionInfo["parameters"]
ticket_num = params["ticket_num"]
try:
async with Incident(client, table_name="incident") as incident:
response = await incident.get_one(Incident.number == ticket_num)
stage_value = response.data["state"].value
desc = response.data["description"]
[...data manipulation, unimportant parts]
What i am having trouble with is trying to mock the client response, every time the actual client gets invoked and it makes the API call which i dont want.
Here is the current version of my unittest:
from fastapi.testclient import TestClient
client = TestClient(app)
#patch("aiosnow.models.table.declared.IncidentModel")
def test_get_ticket_endpoint_valid_ticket_num(self, mock_client):
mock_client.return_value = {"data" : {"state": "new",
"description": "test"}}
response = client.post(
"/snow/get_ticket", json=json.load(self.test_request)
)
assert response.status_code == 200
I think my problem is patching the wrong object, but i am not sure what else to patch.
In your test your calling client.post(...) if you don't want this to go to the Service Now API this client should be mocked.
Edit 1:
Okay so the way your test is setup now the self arg is the mocked IncidentModel object. So only this object will be a mock. Since you are creating a brand new IncidentModel object in your post method it is a real IncidentModel object, hence why its actually calling the api.
In order to mock the IncidentModel.get_one method so that it will return your mock value any time an object calls it you want to do something like this:
def test_get_ticket_endpoint_valid_ticket_num(mock_client):
mock_client.return_value = {"data" : {"state": "new",
"description": "test"}}
with patch.object(aiosnow.models.table.declared.IncidentModel, "get_one", return_value=mock_client):
response = client.post(
"/snow/get_ticket", json=json.load(self.test_request)
)
assert response.status_code == 200
The way variable assignment works in python, changing aiosnow.models.table.declared.IncidentModel will not change the IncidentModel that you've imported into your python file. You have to do the mocking where you use the object.
So instead of #patch("aiosnow.models.table.declared.IncidentModel"), you want to do #patch("your_python_file.IncidentModel")

Mocking in Behave and Flask

I am trying to mock an HTTP request call using mock because I don't want to Behave to call it actually.
So I have this code scenario in matches.py file:
import request
def get_match():
response = request.get("https://example.com")
return response
And in my step definition match_steps.py for behave I have this:
def logoport_matches_response(context):
mock_response = context.text # this is the payload will come from feature file
with patch ('match') as mock_match:
mock_match.get_match.return_value = {"status": "success"}
But it seems this is not working because it still requesting an actual HTTP request.
I need to mock the get_match method to return {"status": "success"} result
Alright, I figure it out, you need to put your initialization inside the mock so:
from mock import patch
from matches import get_match
with patch ('match') as mock_match:
mock_match.return_value = {"status": "success"}
get_match()

In Django how to mock an object method called by views.py during its import?

I am writing System Tests for my Django app, where I test the complete application via HTTP requests and mock its external dependencies' APIs.
In views.py I have something like:
from external_service import ExternalService
externalService = ExternalService
data = externalService.get_data()
#crsf_exempt
def endpoint(request):
do_something()
What I want is to mock (or stub) ExternalService to return a predefined response when its method get_data() is called.
The problem is that when I run python manage.py test, views.py is loaded before my test class. So when I patch the object with a mocked one, the function get_data() was already called.
This solution didn't work either.
First off, don't call your method at import time. That can't be necessary, surely?
If get_data does something like a get request, e.g.
def get_data():
response = requests.get(DATA_URL)
if response.ok:
return response
else:
return None
Then you can mock it;
from unittest.mock import Mock, patch
from nose.tools import assert_is_none, assert_list_equal
from external_service import ExternalService
#patch('external_service.requests.get')
def test_getting_data(mock_get):
data = [{
'content': 'Response data'
}]
mock_get.return_value = Mock(ok=True)
mock_get.return_value.json.return_value = data
response = ExternalService.get_data()
assert_list_equal(response.json(), data)
#patch('external_service.requests.get')
def test_getting_data_error(mock_get):
mock_get.return_value.ok = False
response = ExternalService.get_data()
assert_is_none(response)
For this you'll need pip install nose if you don't already have it.

Writing a Django unit test for a function with a HttpResponse

I'm writing a unit test to check to see if the telecasts key is in the JSON data returned in this function (in my views.py):
def my_function(request, date1='', date2='', date3='', date4=''):
::some other functions...::
return HttpResponse(data, content_type='application/json')
As you see, the JSON I want to check is sent via a HttpResponse as the variable data
This JSON data, when received on the front-end, is structured like:
{"records": [ {"program": "WWE ENTERTAINMENT", "telecasts": 201,...}, {..} ]
So this is how I'm trying to write the unit test, but I'm getting an error when I run it:
def my_test(self):
"""Data returned has telecasts key"""
request = self.client.get(
'/apps/myapp/2014-08-01/2015-06-10/2016-01-13/2016-03-23/',
{dictionary of optional parameters}
)
force_authenticate(request, user=self.user)
response = my_function(
request,
'2014-08-01',
'2015-06-10',
'2016-01-13',
'2016-03-23'
)
telecasts_check = response['records'][0]['telecasts']
self.assertRaises(KeyError, lambda: telecasts_check)
self.client.get makes the request and returns the response so it is totally unnecessary to call myfunction directly to get the response down below.
Another thing is, HttpResponse has a property named content which can be a bytestring or an iterator that stores the response content.
In your case, you can convert that to a dictionary using json.loads and access any values just like you already are doing:
import json
def my_test(self):
...
response = self.client.get(...)
result = json.loads(response.content)
telecasts_check = result['records'][0]['telecasts']
...

Python mock, django and requests

So, I've just started using mock with a Django project. I'm trying to mock out part of a view which makes a request to a remote API to confirm a subscription request was genuine (a form of verification as per the spec I'm working to).
What I have resembles:
class SubscriptionView(View):
def post(self, request, **kwargs):
remote_url = request.POST.get('remote_url')
if remote_url:
response = requests.get(remote_url, params={'verify': 'hello'})
if response.status_code != 200:
return HttpResponse('Verification of request failed')
What I now want to do is to use mock to mock out the requests.get call to change the response, but I can't work out how to do this for the patch decorator. I'd thought you do something like:
#patch(requests.get)
def test_response_verify(self):
# make a call to the view using self.app.post (WebTest),
# requests.get makes a suitable fake response from the mock object
How do I achieve this?
You're almost there. You're just calling it slightly incorrectly.
from mock import call, patch
#patch('my_app.views.requests')
def test_response_verify(self, mock_requests):
# We setup the mock, this may look like magic but it works, return_value is
# a special attribute on a mock, it is what is returned when it is called
# So this is saying we want the return value of requests.get to have an
# status code attribute of 200
mock_requests.get.return_value.status_code = 200
# Here we make the call to the view
response = SubscriptionView().post(request, {'remote_url': 'some_url'})
self.assertEqual(
mock_requests.get.call_args_list,
[call('some_url', params={'verify': 'hello'})]
)
You can also test that the response is the correct type and has the right content.
It's all in the documentation:
patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)
target should be a string in the form ‘package.module.ClassName’.
from mock import patch
# or #patch('requests.get')
#patch.object(requests, 'get')
def test_response_verify(self):
# make a call to the view using self.app.post (WebTest),
# requests.get makes a suitable fake response from the mock object

Categories

Resources