How can I assure my SoapUI MockService will return the correct answer to the correct request? The response itself is generated inside the MockService script "OnRequest" and stored in property -
context.content
The content of the response is only
${content}
But if two or more requests happen at the same time both scripts get excuted at the same time and the response is not always correct because of the reassignment of the property.
Maybe - can I somehow synchronize executions of the script so that only one of them is running at the same time?
Dispatch responses on some criteria in request, for ex.:
def postcode = new XmlParser().parseText(postcodes[0].xmlText()).text()
if (postcode == "abcd") {return "response 1"}
else if (postcode == "efgh") {return "response 2"}
In your case mock context is the object that needs to be synchronized. please check weather it got synchronized or not . when two threads[requests to mock] accessing at the same time . they both manipulate the same context at same time . hence context is the object you need to synchronize.
Related
Let's say I have a Fastapi application like this (This code is taken from documentations):
app = FastAPI()
#app.get("/foo")
async def read_main():
return {"msg": "Hello World"}
I believe there are two ways of testing this view. The first one is by the use of a client object. For instance:
client = TestClient(app)
def test_read_main():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"msg": "Hello World"}
However, I think this is not a unit test. It is more like an integration test. Because we are actually running fastapi codes as well.
The second option which in my opinion is closer to unit test definition is to run the function directly:
def test_read_main():
response = read_main()
assert response == {"msg": "Hello World"}
Similarly, in Django, we can directly call the view function, or by using a client object.
My first question is which one is better?
Let's say we chose one of them and now in order to prevent calling the database I have mocked the database. Now I want to test a view that just checks if something exists in the database. My second question is what is the point of testing such view? Becuase after mocking the database, we know what would happen when calling the database with given arguments.
I've got a couple models, Car and CertifyRequest. When a Car instance is created, modified or deleted I need to create a CertifyRequest, which in turn needs to be manually approved. The CertifyRequest instance contains the time it was created.
I've tested creating and modifying by injecting context={"now": …} into a CarSerializer instance, but I can't figure out how to do the equivalent when deleting:
Delete requests are never passed to the serializer, so I can't access the context in the same way.
I can override destroy in the ModelViewSet and use get_serializer_context within it, but
I can't seem to pass the serializer to the ModelViewSet instance and
the implementation returns a completely different context anyway.
I do not want to use a horrible hack like an optional query parameter or testing that the time is "close to" the current test client time.
The hack I'm using currently is to set an extra now property on the Request which I pass to the view, and to look for that inside destroy.
If you're using Django's timezone.now() in your view to get the current time, you can mock that method to return a specific time in your tests and assert against that.
def test_destroy_car():
client = APIClient()
#mock.patch("application.views.timezone.now") as now:
destroy_time = datetime.datetime(2019, 4, 23, 11, 2, 0)
now.return_value = destroy_time
response = client.destroy("/api/car/12345/")
assert response.status_code == status.HTTP_204_NO_CONTENT, "The request to delete did not return a 204 response"
certify_request = CertifyRequest.objects.order_by("id").last()
assert certify_request.created_at == destroy_time, "CertifyRequest destroy time is incorrect"
How can i access session variable using response object in django test.
def test(self):
postdata={'user':'staff'}
self.client.login(username='vishnu',password='vishnu#12345')
session=self.client.session
session['user']='manager'
session.save()
response=self.client.post(reverse('userhome'),postdata)
self.assertEqual(session['user'],'staff')
This test fails when run. In the above test, after calling post request the session variable 'user' will change to staff. How do i check the change? session['user'] gives same result after request. However in the view function request.session['user'] gives exact result.
How can i access session data from response?
Checking the final session state in self.client.session is working for me. self.client and response.client are the same object, so you could use response.client.session if that better signals intent:
def test(self):
postdata={'user':'staff'}
self.client.login(username='vishnu',password='vishnu#12345')
session=self.client.session
session['user']='manager'
session.save()
response=self.client.post(reverse('userhome'),postdata)
self.assertIn('user', self.client.session)
self.assertEqual(self.client.session['user'], 'staff')
self.assertIn('user', response.client.session)
self.assertEqual(response.client.session['user'], 'staff')
The documentation would seem to suggest that this wouldn't work: "To modify the session and then save it, it must be stored in a variable first (because a new SessionStore is created every time this property is accessed)." But I guess that's only true of setting the session before sending a request? Not sure, but it could use some clarification.
I'm building unit tests for this webapp2 handler (built for GAE)
class PushNotificationHandler(webapp2.RequestHandler):
def post(self):
UserNotification.parse_from_queue(self.request)
return
app = webapp2.WSGIApplication([
(r'/push/notification', PushNotificationHandler),
], debug=True)
One test is
#patch.object(UserNotification, 'parse_from_queue')
def test_post_webapp(self, p_parse_from_queue):
response = webtest.TestApp(app).post('/push/notification')
eq_(response.status_int, 200)
p_parse_from_queue.assert_called_once_with(response.request)
The HTTP reply is OK, but the mock assertion fails:
Expected call: parse_from_queue(<TestRequest at 0x105a89850 POST http://localhost/push/notification>)
Actual call: parse_from_queue(<Request at 0x105a89950 POST http://localhost/push/notification>)
I can't understand why the request is not the correct one (looks like a deep copy). Is there anything wrong with the unit-test, or is that the way webapp2 handle requests. In the second case, is there a way to test it, without creating a separate test to test PushNotificationHandler.post()
Thanks
I've used mock's call_args in a similar situation. You can do something like this:
request = p_parse_from_queue.call_args[0][0]
self.assertEqual(request.url, "foo")
self.assertEqual(request.*, *)
The [0][0] gives you the first passed argument assuming that you are using ordered arguments and not keyword arguments.
You can then proceed to check other relevant attributes of the request object to make sure it is behaving as expected.
I'm reading Miguel Grindberg's great new book "Flask Web Development", and don't understand part of this code on page 107. . .
#auth.before_app_request
def before_request():
if current_user.is_authenticated() \
and not current_user.confirmed \
and request.endpoint[:5] != 'auth.':
return redirect(url_for('auth.unconfirmed'))
I do not understand what the purpose of the slice ([:5]) is in the line. . .
and request.endpoint[:5] != 'auth.':
Here's his explanation for the code. #3 is referring to the line in question.
"The before_app_request handler will intercept a request when three conditions are
true:
1. A user is logged in (current_user.is_authenticated() must return True).
2. The account for the user is not confirmed.
3. The requested endpoint (accessible as request.endpoint) is outside of the authentication
blueprint. Access to the authentication routes needs to be granted, as
those are the routes that will enable the user to confirm the account or perform
other account management functions."
My question is, why the slice ([:5])? To me it seems the code would match his explanation perfectly without the slice. He says the purpose is to catch any endpoint outside of "auth", so it seems to me the code should be. . .
and request.endpoint != 'auth.':
Any help would be GREATLY appreciated. Thanks.
request.endpoint holds data like auth.unconfirmed or main.whatever
the code here is a check for the blueprint part (in this case"auth.")
after line
return redirect(url_for('auth.unconfirmed'))
was executed, this whole code block gets called again (request.endpoint having the value 'auth.unconfirmed', without the slice this would be a infinite loop)
Long story short: do not redirect if in auth blueprint
Concerning your comment:
from the doc:
#before_app_request
Such a function is executed before each request,
even if outside of a blueprint.
So after return redirect(url_for('auth.unconfirmed')) the block is called again (new request), but now request.endpoint is the string 'auth.unconfirmed'. Then request.endpoint[:5] != 'auth.' is false and then there is no further redirect (otherwise there would be the endless loop)
request.endpoint is a string. It has no knowledge about blueprints and views. The slice is there because request.endpoint contains more than just 'auth.', for example 'auth.unconfirmed'. This could also have been written as request.endpoint.startswith('auth.').
request.endpoint != 'auth.' will always evaluate to true because there will never be an endpoint with that name. If you tried to evaluate url_for('auth.') you'd get a BuildError.