I have a controller method that I'm annotating like so:
#Secured(['ROLE_ADMIN'])
def save() {
... // code ommitted
}
I'm trying to write a unit test to verify that only the admin user can hit the URL:
def "Only the admin user should be able to invoke save"() {
given:
def user = createNonAdminUser() // let's pretend this method exists
controller.springSecurityService = Mock(SpringSecurityService)
controller.springSecurityService.currentUser >> user
when:
controller.save()
then:
view ==~ 'accessdenied'
}
However, the view returned is the save view and not the access denied view. It looks like it's bypassing the #Secured annotation altogether. Is there a way to test #Secured annotations from either a unit test or integration test?
Try this:
SpringSecurityUtils.doWithAuth('superuser') {
controller.save()
}
http://greybeardedgeek.net/2011/05/13/testing-grails-controllers-with-spock/
You would need to login the user before calling controller save if you are not doing it already in createNonAdminUser().
SpringSecurityUtils.reauthenticate username, password
Possibly related to this question.
Related
Hi Everyone I'm just searching for the feature of Flask.
What I want to do is to branch controller with query-parameter like Spring #RequestMapping EXAMPLE
I want Flask Controller to work when specific params exist.
Do that features exist In Flask?
I don't want to branch with if statement in method
I dont want to like this.
from flask import request
#app.route('/user')
def user():
actions = request.args.get('actions')
if actions == "migration"
pass
if actions == "something"
pass
....
I want to like this
#app.route('/user', params={"actions=migration"})
def user_migration():
pass
#app.route('/user', params={"actions=something"})
def user_something():
pass
You can just add that logic in your "controller" itself, like so:
from flask import request
#app.route('/home/fetch')
def data():
# here we want to get the value of user (i.e. ?personId=some-value)
personId = request.args.get('personId')
if personId == <your-value-here>
If you know what your params are always going to be then why not just set it to the route itself:
#app.route('/user/migration')
def user_migration():
pass
#app.route('/user/something')
def user_something():
pass
Im writing unit tests for a Django package (Django-Notifications) and want to unit test that a notification is deleted when the 'delete' button is pressed.
I know how to test forms:
response = self.client.post(
reverse('webpage'), data={
'question': 'some question'},
HTTP_REFERER=referer,
follow=True
)
And I know how to mock users and sign them in, but have no idea how to unit test non-form buttons =.
More specifically, I dont know how to:
Create the mock notification
Test that the button successfully removes the notification
(Perhaps this is something that should only be functional tested?)
This is all I have so far:
def test_delete_button_removes_notification(self):
user = User.objects.create_superuser('username')
self.client.force_login(user)
# create notification
# simulate button press
# assert notification count == 0
Thank you.
I've enabled login authentication for my django app. Unit tests for views are not working because they get stuck at the login page. Setting a breakpoint immediately after the view's response is returned and using
print response.content
results in output that contains the phrase 'please login'
How do I setup a user so the testcase can login? I've tried using my username and password, but it doesn't work in the unit test context.
The following code inserted at the beginning of the testcase creates a user, logs them in, and allows the rest of the test to contiue
self.user = User.objects.create_user(username='testuser', password='12345')
login = self.client.login(username='testuser', password='12345')
I'm writing some tests for my Django Rest Framework and trying to keep them as simple as possible. Before, I was creating objects using factory boy in order to have saved objects available for GET requests.
Why are my POST requests in the tests not creating an actual object in my test database? Everything works fine using the actual API, but I can't get the POST in the tests to save the object to make it available for GET requests. Is there something I'm missing?
from rest_framework import status
from rest_framework.test import APITestCase
# from .factories import InterestFactory
class APITestMixin(object):
"""
mixin to perform the default API Test functionality
"""
api_root = '/v1/'
model_url = ''
data = {}
def get_endpoint(self):
"""
return the API endpoint
"""
url = self.api_root + self.model_url
return url
def test_create_object(self):
"""
create a new object
"""
response = self.client.post(self.get_endpoint(), self.data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, self.data)
# this passes the test and the response says the object was created
def test_get_objects(self):
"""
get a list of objects
"""
response = self.client.get(self.get_endpoint())
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data)
# this test fails and says the response is empty [] with no objects
class InterestTests(APITestCase, APITestMixin):
def setUp(self):
self.model_url = 'interests/'
self.data = {
'id': 1,
'name': 'hiking',
}
# self.interest = InterestFactory.create(name='travel')
"""
if I create the object with factory boy, the object is
there. But I don't want to have to do this - I want to use
the data that was created in the POST request
"""
You can see the couple lines of commented out code which are the object that I need to create through factory boy because the object does not get created and saved (although the create test does pass and say the object is created).
I didn't post any of the model, serializer or viewsets code because the actual API works, this is a question specific to the test.
First of all, Django TestCase (APITestCase's base class) encloses the test code in a database transaction that is rolled back at the end of the test (refer). That's why test_get_objects cannot see objects which created in test_create_object
Then, from (Django Testing Docs)
Having tests altering each others data, or having tests that depend on another test altering data are inherently fragile.
The first reason came into my mind is that you cannot rely on the execution order of tests. For now, the order within a TestCase seems to be alphabetical. test_create_object just happened to be executed before test_get_objects. If you change the method name to test_z_create_object, test_get_objects will go first. So better to make each test independent
Solution for your case, if you anyway don't want database reset after each test, use APISimpleTestCase
More recommended, group tests. E.g., rename test_create_object, test_get_objects to subtest_create_object, subtest_get_objects. Then create another test method to invoke the two tests as needed
I'm trying to figure out how to test middleware in django. The middleware I'm writing logs in a user under certain conditions (if a key sent in email is valid). So obviously I'm dependent on django.contrib.auth and django.contrib.sessions.
I'm running into problems testing the login portion. I'm making a request like this:
user = User.objects.create_user('user', 'user#example.org', 'password')
key = LoginKey.objects.create(user=user)
request = self.factory.get('/', data={'auth_key': key.hash}) # self.factory is a RequestFactory()
self.middleware.process_request(request) # self.middleware is MyMiddleware()
That fails due to the session not being set. So next, I wrote a little snippet in my test class:
def make_session(self, request):
SessionMiddleware().process_request(request)
and that fails due to 'User' object has no attribute 'backend'. I'm not sure on the meaning of that, but I suspect I need to run all the middlewares I have installed.
I don't really want to make a fake view for this just to run a middleware, but I can't see another option at this point.
So I just wanted to know, before I have to chase this rabbit all the way down the hole, is there a way of doing this that doesn't require as much duct tape?
You should use the test client for this. That will ensure that the middleware is run and the session keys created.
response = self.client.get('/?auth_key=%s' % key.hash)
self.assertTrue(response.context['user'].is_authenticated()) # for example