python unittest function expected called but the result is none called - python

This is my function :
#File lambda_function.py
from calculate import addition
def lambda_handler(event, context):
try:
v = addition(2)
return {
"statusCode": 200,
"body": {
"message": v,
},
}
except Exception as err:
return {
"statusCode": 500,
"headers": {},
"body": {
"message": "error.generic",
},
}
#File calculate.py
def addition(x):
return x + 1;
File test_lambda_function.py
from unittest.mock import patch
import lambda_function as lambda_function
import calculate
class TestLambdaFunction(unittest.TestCase):
def setUp(self):
self.member_id = 100
self.event = {
"body": "None",
}
#patch('calculate.addition', return_value=3)
def test_lambda_handler(self, mocked_addition):
lambda_function.lambda_handler(self.event, {})
self.assertEqual(mocked_addition.call_count, 1)
Test result:
test_lambda_function.py:114 (TestLambdaFunction.test_lambda_handler)
1 != 0
Expected :0
Actual :1
Please can you explain me why the test result tell me that the function isn't called. did I make a mistake in import?

Related

python exceptions decorators

Task 1: Write your own exception (your class) 'AuthError' raise ->
ArithmeticError(AuthError)
Task 2: write a decorator that, in case of missing data (inside request_from_user)
from authorization raises an 'AuthError' exception
Task 3: if successful, return Object (class) 'RequestManager' + 2 methods for validation
Task 4: Implement a "Help class" in which to implement at least 3 methods that you will need in the future. And also save the constant Pi as a property of the class.
request_from_user1 = {
"url": "localhost/home/",
"method": "GET",
"data": {"попытка входа": 1},
"timeout": 3000,
"headers": {
"Authorization": 'Bearer admin qwerty12345',
},
}
request_from_user2 = {
"url": "localhost/",
"method": "POST",
"data": {"попытка входа": 1},
"timeout": 3000,
"headers": {},
}
class AuthError(Exception):
def __init__(self, exception_text: str):
self.exception_text = exception_text
def return_error(self):
return f'ATTENTION: AN ERROR HAS OCCURSED: {self.exception_text}'
def check_user_request():
try:
raise AuthError(exception_text="incorrect login")
except AuthError as error:
error = error.return_error()
print(error)
print(check_user_request())
My attempt, but i dont know what to do next, can you help me please

Format JSON output from AWS Lambda function

Lambda Program
import json
import boto3
from pprint import pprint
def lambda_handler(event, context):
# TODO implement
#instance = event['instanceid']
client = boto3.client("ec2")
status = client.describe_instance_status(InstanceIds=[
'i-0c52lidc87f',
],)
#pprint(status)
for i in status["InstanceStatuses"]:
print("AvailabilityZone :", i["AvailabilityZone"])
print("InstanceId :", i["InstanceId"])
print("InstanceState :", i["InstanceState"])
print("InstanceStatus", i["InstanceStatus"])
return {
'body': ("Instance Status :", i["InstanceState"],i["InstanceId"],i["AvailabilityZone"])
}
Output
{
"statusCode": 200,
"body": [
"Instance Status :",
{
"Code": 16,
"Name": "running"
},
"i-0c52lidc87f",
"ca-central-1a"
]
}
I'm getting the above response from my lambda function on AWS - how can change this to readable format - just Instance ID: i-0c5e8c3c87f and Status: Running
Please help!
Youre JSON isnt formatted properly, if Instance Status is supposed to be a tuple, try:
return {
"body": {
"Instance Status":{
"InstanceState": i["InstanceState"]["Name"],
"InstanceId": i["InstanceId"],
"AvailabilityZone": i["AvailabilityZone"]
}
}

Union type cannot resolve Object Type at Runtime

I am setting up a GraphQL Server with Python using Starlette and Graphene and ran into a problem I cannot find a solution for. The Graphene Documentation does not go into detail regarding the union type, which I am trying to implement.
I set up a minimum example based on the graphene documentation which you can run to replicate this problem
import os
import uvicorn
from graphene import ObjectType, Field, List, String, Int, Union
from graphene import Schema
from starlette.applications import Starlette
from starlette.graphql import GraphQLApp
from starlette.routing import Route
mock_data = {
"episode": 3,
"characters": [
{
"type": "Droid",
"name": "R2-D2",
"primaryFunction": "Astromech"
},
{
"type": "Human",
"name": "Luke Skywalker",
"homePlanet": "Tatooine"
},
{
"type": "Starship",
"name": "Millennium Falcon",
"length": 35
}
]
}
class Human(ObjectType):
name = String()
homePlanet = String()
class Droid(ObjectType):
name = String()
primary_function = String()
class Starship(ObjectType):
name = String()
length = Int()
class Characters(Union):
class Meta:
types = (Human, Droid, Starship)
class SearchResult(ObjectType):
characters = List(Characters)
episode = Int()
class RootQuery(ObjectType):
result = Field(SearchResult)
#staticmethod
def resolve_result(_, info):
return mock_data
graphql_app = GraphQLApp(schema=Schema(query=RootQuery))
routes = [
Route("/graphql", graphql_app),
]
api = Starlette(routes=routes)
if __name__ == "__main__":
uvicorn.run(api, host="127.0.0.1", port=int(os.environ.get("PORT", 8080)))
If you then go to http://localhost:8080/graphq and enter the following query
query Humans{
result {
episode
characters {
... on Human {
name
}
}
}
}
I get this error
{
"data": {
"result": {
"episode": 3,
"characters": null
}
},
"errors": [
{
"message": "Abstract type Characters must resolve to an Object type at runtime for field SearchResult.characters with value \"[{'type': 'Droid', 'name': 'R2-D2', 'primaryFunction': 'Astromech'}, {'type': 'Human', 'name': 'Luke Skywalker', 'homePlanet': 'Tatooine'}, {'type': 'Starship', 'name': 'Millennium Falcon', 'length': 35}]\", received \"None\".",
"locations": [
{
"line": 4,
"column": 5
}
]
}
]
}
which I am now stuck with. Maybe someone has done this already and can help out? How can I resolve this at runtime. I have already tried different approaches for example I changed classes Character and RootQuery:
class Character(Union):
class Meta:
types = (Human, Droid, Starship)
def __init__(self, data, *args, **kwargs):
super().__init__(*args, **kwargs)
self.data = data
self.type = data.get("type")
def resolve_type(self, info):
if self.type == "Human":
return Human
if self.type == "Droid":
return Droid
if self.type == "Starship":
return Starship
class RootQuery(ObjectType):
result = Field(SearchResult)
#staticmethod
def resolve_result(_, info):
return {**mock_data, "characters": [Character(character) for character in mock_data.get('characters')]}
resulting in
{
"data": {
"result": {
"episode": 3,
"characters": [
{},
{
"name": null
},
{}
]
}
}
}
Any ideas would be very appreciated!
jkimbo answered the question here:
class Character(Union):
class Meta:
types = (Human, Droid, Starship)
#classmethod
def resolve_type(cls, instance, info):
if instance["type"] == "Human":
return Human
if instance["type"] == "Droid":
return Droid
if instance["type"] == "Starship":
return Starship
class RootQuery(ObjectType):
result = Field(SearchResult)
def resolve_result(_, info):
return mock_data
Note I'm just returning mock_data and I've updated the resolve_type method to switch based on the data. The Union type uses the same resolve_type method as Interface to figure out what type to resolve to at runtime: https://docs.graphene-python.org/en/latest/types/interfaces/#resolving-data-objects-to-types

Monkeypatching a requests.get() function

I am testing my code, so far so good. But now I have to test a function using requests.get() to make an API call.
As far as I understand, I have to 'mock' this function in my test.
My function calls Google Maps API, and in my test I added the wanted output:
result =
{
"candidates":[
{
"geometry":{
"location":{
"lat":-34.5453062,
"lng":-58.44977489999999
}
},
"name":"Stade Monumental Antonio Vespucio Liberti",
"place_id":"ChIJ340B5jq0vJURijD6W6dgfz0"
}
]
}
return json.dumps(result)
This the function I am testing:
def get_lat_lng (self):
self.input_api = '%20'.join(self.parsed_question)
self.input_api = ' '.join(self.parsed_question)
self.google_api_url = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input={}&inputtype=textquery&fields=geometry,name,place_id&types=point_of_interest&key={}'.format (self.input_api, api_key)
self.r = requests.get (url = self.google_api_url)
self.data = self.r.json()
self.name = self.data['candidates'][0]['name']
self.place_id = self.data['candidates'][0]['place_id']
self.lat = self.data['candidates'][0]['geometry']['location']['lat']
self.lng = self.data['candidates'][0]['geometry']['location']['lng']
return (self.lat, self.lng, self.place_id)
And my test so far:
def test_get_lat_lng (monkeypatch):
monkeypatch.setattr('requests.get', mock_get_lat_lng)
This is the error code I get when trying to run the test:
self.r = requests.get (url = self.google_api_url)
> self.data = self.r.json()
E AttributeError: 'str' object has no attribute 'json'
I don't understand since I use json.dumps() on my desired output to "mock" an answer from requests.get(), how can it be a 'str' object? Looking for the type of self.r I get <class 'requests.models.Response'>.
Making mock_get_lat_lng() a class did the trick. Here is my final working test:
class mock_get_lat_lng():
def __init__(self, url):
pass
def json(self):
result = {
"candidates": [
{
"geometry": {
"location": {
"lat": -34.5453062,
"lng": -58.44977489
}
},
"name": "Stade Monumental Antonio Vespucio Liberti",
"place_id": "ChIJ340B5jq0vJURijD6W6dgfz0"
}
]
}
return result

Slimming JSON messages down without deriving from `list`

Consider a server generating JSON messages for a to-do list.
import json
class Action(object):
def __init__(self, what, when):
self.what = what
self.when = when
class Actions(object):
def __init__(self):
self.actions = []
def insert(self, action):
self.actions.append({'action': 'insert_todo',
'detail': {'what': action.what,
'when': action.when}})
class Batch(object):
def __init__(self):
self.urgent_actions = Actions()
self.ordinary_actions = Actions()
self.urgent_actions.insert(Action('tidy up', '8am'))
def jdefault(o):
return o.__dict__
def output_json():
batch = Batch()
mystr = json.dumps(batch,
default=jdefault,
indent=4)
print(mystr)
output_json()
This works fine, and we get the message:
{
"urgent_actions": {
"actions": [
{
"action": "insert_todo",
"detail": {
"what": "tidy up",
"when": "8am"
}
}
]
},
"ordinary_actions": {
"actions": []
}
}
But repeating actions inside both priorities of actions and in each message is asking for some clean-up.
We can do that by deriving Actions from list:
class Actions(list):
def __init__(self, *args):
list.__init__(self, *args)
def insert(self, action):
self.append({'action': 'insert_todo',
'detail': {'what': action.what,
'when': action.when}})
And we get indeed the slimmer JSON message:
{
"urgent_actions": [
{
"action": "insert_todo",
"detail": {
"what": "8am",
"when": "8am"
}
}
],
"ordinary_actions": []
}
Yet,
deriving
from
list
is
far
from
the best idea.
What other (idiomatic) way would you use to get the slimmer message without deriving from list?
The messages are to be sent through Flask, in case you'd also like to critique the use of json.dumps.
Rather than change the classes, you could delegate defining the structure of the json to the jdefault function.
def jdefault(o):
if isinstance(o, Batch):
return o.__dict__
if isinstance(o, Actions):
return o.actions
raise TypeError("Object of type {} is not JSON serializable".format(type(o)))
Which generates the desired output:
{
"urgent_actions": [
{
"action": "insert_todo",
"detail": {
"what": "tidy up",
"when": "8am"
}
}
],
"ordinary_actions": []
}
This way you separate the concerns of your objects' structure and serialisation.

Categories