pytest override function thats not in a class - python-3.x

So I'm trying to understand how I can create a unit test that tests a function, which calls other functions. I want to be able to test this function, and override one of the functions that it calls because I don't want it to actually go out and make a call, I want to provide a return_value for that function.
So far I've seen this is mainly doable if you're using a class, but this is an API endpoint and I'm not using a class in this case. Here is the actual endpoint (simplified):
def _get_mock_request(self, queryStringParameters):
return {
"headers": {"x-api-key": "SOME-KEY"},
"requestContext": {
"resourceId": "t89kib",
"authorizer": {
"x-authorizer-key": "SOME KEY",
"principalId": "9de3f415a97e410386dbef146e88744e",
"integrationLatency": 572,
},
},
"pathParameters": {"proxy": "unittest"},
"resource": "/{proxy }",
"httpMethod": "GET",
"queryStringParameters": queryStringParameters,
"body": None,
}
def get(request, response):
"""ApiGateway GET function"""
if validator.valid_raw_data_request(request, response):
handle_query(request, response)
return response
So what I am trying to do, is simply just override the handle_query function, and tell it what return value I want. Here is what I've currently tried (and many different variations/flavors of this):
#mock.patch('requests.get', side_effect=mock_response.requests_get)
#mock.patch('application.v1.logic.common.raw_data_request_handler.handle_query')
#mock.patch.dict(os.environ, {'DEFAULT_ATHENA_MAX_RESULTS': '100'})
def test_get_pass(self, mock_handle_query, mock_get):
mock_handle_query.return_value = raw_fields_json_mock
Except I still see this function being called, and then also going out and making API requests which I don't want. I know this is definitely something I'm not quite understanding about Pytest (fairly new to Python in general, came from Node). But I just don't know what im missing here. Based on everything I've googled, this should work.

Related

Groovy script assertion that validates the presence of some values in a JSON response

So I'm using an testing tool called ReadyAPI and for scripting it uses the Groovy language. I'm not familiar with the language and the fact that it's based on Java it somehow makes it even worse.
Now I'm trying to validate a REST response in JSON with an assertion that checks that certain elements exist in the response.
This is the code that I have now:
import groovy.json.*
def response = context.expand( 'RequestResponseHere' )
def object = new JsonSlurper().parseText(response)
assert response.contains("CODE1")
assert response.contains("CODE2")
assert response.contains("CODE3")
assert response.contains("CODE4")
The assertion seems to work but I was wondering if there is maybe a simpler way to do it than to have to write so many lines and making it less 'bulky'?
Any help is greatly appreciated.
Thank you!
Added an example of the json data that I have to parse:
What I need is to check that the value of "code" is always part of a list of acceptable values e.i. CODE1, CODE2, etc.
{
"_embedded": {
"taskList": [
{
"code": "CODE1",
"key": 123
},
{
"code": "CODE2",
"key": "234"
},
{
"code": "CODE3",
"key": "2323"
},
{
"code": "CODE4",
"key": "7829"
},
{
"code": "CODE5",
"key": "8992"
}
]
}
}
If you want to check for certain things to be there, you can DRY that
code with:
["code1","code2"].each{ assert response.contains(it) }
And as stated in the comments, if you want to make sure, "all are there,
but I don't care for the order", extracting the values and comparing it
as results can shorten this:
assert response._embeded.taskList*.code.toSet() == ["code1", ...].toSet()
Note the use of *., which is the "spread operator". It is basically
the same as ...collect{ it.code }. Then comparing the string sets
does the rest (this is fine if you are comparing not to many items since
the power assert will print all the items along the failed assertion; if
you have to find the proverbial needle in the haystack, you are better
off writing something smarter to check the two sets).
The assertion seems to work but I was wondering if there is maybe a
simpler way to do it than to have to write so many lines and making it
less 'bulky'?
Unclear what it is that is bulky but if what you want is to lessen the number of statements, one thing you could do is use a single assert.
Instead of this:
assert response.contains("CODE1")
assert response.contains("CODE2")
assert response.contains("CODE3")
assert response.contains("CODE4")
You could have this:
assert response.contains("CODE1") &&
response.contains("CODE2") &&
response.contains("CODE3") &&
response.contains("CODE4") &&

What does Depends with no parameter do?

I am trying to implement JWT with fastapi.
Currently looking at the following libraries
fastapi-users
FastAPI JWT Auth
In both cases, I see Depends() in method parameter.
What does Depends do when there is nothing in the parameter?
https://github.com/frankie567/fastapi-users/blob/master/fastapi_users/router/auth.py
#router.post("/login")
async def login(
response: Response, credentials: OAuth2PasswordRequestForm = Depends()
):
https://indominusbyte.github.io/fastapi-jwt-auth/usage/basic/
#app.post('/login')
def login(user: User, Authorize: AuthJWT = Depends()):
I undestand when there's a function inside the parameter but would you teach me what it does when there's no parameter with Depends?
Depends() without arguments is just a shortcut for classes as dependencies.
You see that we are having some code repetition here, writing CommonQueryParams twice:
commons: CommonQueryParams = Depends(CommonQueryParams)
FastAPI provides a shortcut for these cases, in where the dependency is specifically a class that FastAPI will "call" to create an instance of the class itself.
For those specific cases, you can do the following:
Instead of writing:
commons: CommonQueryParams = Depends(CommonQueryParams)
...you write:
commons: CommonQueryParams = Depends()
You declare the dependency as the type of the parameter, and you use Depends() as its "default" value (that after the =) for that function's parameter, without any parameter in Depends(), instead of having to write the full class again inside of Depends(CommonQueryParams).
In both cases, I see Depends() in method parameter. What does Depends do when there is nothing in the parameter?
It's a great question.
Assume you have the following code.
from fastapi import FastAPI, Depends
from pydantic import BaseModel
from typing import Optional
class Location(BaseModel):
city: str
country: str
state: str
app = FastAPI()
#app.post("/withoutdepends")
async def with_depends(location: Location):
return location
#app.post("/withdepends")
async def with_depends(location: Location = Depends()):
return lcoation
We have the same Location model in two different endpoints, one uses Depends other one not.
What is the difference?
Since FastAPI is based on OpenAPI specification, we can start discovering the difference from auto-generated Swagger's docs.
This is without Depends, it expects a Request Body.
This is with Depends, it expects them as Query parameters.
How this is useful and how it works?
Actually, this is it, it expects a Callable there.
But when you use a Pydantic Model with Depends, it actually creates a query parameter for parameter inside init __init__ function.
So for example, this is the model we used above.
class Location(BaseModel):
city: str
country: str
state: str
It becomes this with Depends.
class Location(BaseModel):
def __init__(self, city: str, country: str, state: str) -> None:
...
Then they will become query parameters. This is the OpenAPI schema for the /withdepends endpoint.
"parameters": [
{
"required":true,
"schema":{
"title":"City",
"type":"string"
},
"name":"city",
"in":"query"
},
{
"required":true,
"schema":{
"title":"Country",
"type":"string"
},
"name":"country",
"in":"query"
},
{
"required":true,
"schema":{
"title":"State",
"type":"string"
},
"name":"state",
"in":"query"
}
]
This is the OpenAPI schema it created for /withoutdepends endpoint.
"requestBody": {
"content":{
"application/json":{
"schema":{
"$ref":"#/components/schemas/Location"
}
}
},
"required":true
}
Conclusion
Instead of request body, you can create query parameters with the same model.
Pydantic models are very useful for the cases when you have +5 parameters. But it expects a request body by default. But OpenAPI specification doesn't allow request body in GET operations. As it says in the specification.
GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics as per RFC 7231.
So by using Depends you are able to create query parameters for your GET endpoint, with the same model.

Handling nulls on get calls in Vogels.js

I'm using Vogel.js to connect to Amazon DynamoDB. It's great, however one thing I'm struggling with is that a call such as
MyEntity.get({ my_key: keyValue }, callback);
will either return null if there is no results, or will return a wrapper object.
If I just want to read MyEntity as an object, it appears that in my callback I then have to do
const myEntityAsAnObject = queryResult.get();
however, this will throw if there was no results. So then I have to do some null checking before I do the get. Which I could use lodash or something for, but I'm wondering - is there a nicer way to do this? something like
MyEntity.getAsObject({ my_key: keyValue }, callback);
that will always return the unwrapped object?
The least-inelegant thing I can think of is a higher order function wrapper:
function attrs(callback) {
return function attrsInner(error, model) {
callback(error, model && model.get())
}
}
MyEntity.get({ my_key: keyValue }, attrs(callback));
You could also consider monkey patching the vogels model class prototype in a similar fashion, but I think that would violate the principle of least surprise for someone maintaining your code.

Workaround for lack of generators/yield keyword in Groovy

Wondering if there is a way I can use sql.eachRow like a generator, to use it in a DSL context where a Collection or Iterator is expected. The use case I'm trying to go for is streaming JSON generation - what I'm trying to do is something like:
def generator = { sql.eachRow { yield it } }
jsonBuilder.root {
status "OK"
rows generator()
}
You would need continuation support (or similiar) for this to work to some extend. Groovy does not have continuations, the JVM also not. Normally continuation passing style works, but then the method eachRow would have to support that, which it of course does not. So the only way I see is a makeshift solution using threads or something like that. So maybe something like that would work for you:
def sync = new java.util.concurrent.SynchronousQueue()
Thread.start { sql.eachRow { sync.put(it) } }
jsonBuilder.root {
status "OK"
rows sync.take()
}
I am not stating, that this is a good solution, just a random consumer-producer-work-around for your problem.

Grails Spring Security get assigned roles to a method

I would like to have a test that goes through all methods available in a controller and retrieves roles associated with these methods. I understand that it should be a functional test (as opposed to a unit test), but I still do not know how to request the list of roles associated with a method.
Let's say I have this controller:
#Secured("hasAnyRole('ROLE_1')"
class MyController {
def methodA() {}
#Secured("hasAnyRole('ROLE_2')"
def methodB() {}
}
In my test I would like to have something like this:
assertEquals(['ROLE_1'],getRoles(MyController.class, "methodA"))
assertEquals(['ROLE_1', 'ROLE_2'],getRoles(MyController.class, "methodB"))
Any suggestions?
Thanks.
You can do this with the Reflection API. Something like:
Method m = MyController.class.getMethod("methodB");
Annotation[] annos = m.getAnnotations();
But I don't think that's a good validation for your method, since it only ensure that you write the role name correctly. I think it's better you try to call the action and check if the process redirect to denied.
#TestFor(MyController)
class MyControllerTests {
#Test
void shouldRedirectToDenied() {
SpringSecurityUtils.doWithAuth('username') {
controller.methodB()
assert controller.response.redirectedUrl == '/login/denied'
}
}
}
The doWithAuth closure will mock an authentication for the username, so it's the same to say: "do this code as if the username was logged in successfully".
It seems that you will need to use functional tests indeed. See Burt's comment. I'm still think that's not a valid effort create a test only to validate if the method have the annotation.

Resources