Include authentication.
Opened this issue · 1 comments
Would be nice to have demo of how to integration test controllers when authentication is in play.
Yes, I see how authentication is a common problem many devs are wrestling with. I thought about adding something about auth (both, authentication and authorization) in the past but decided that this is not the right place. Auth is an important aspect but the purpose of this repo (and its corresponding blog post) is to explore different categories of tests first and foremost, while being agnostic about the problem domain of your application.
The problem is that talking about authentication is opening a huge can of worms.
- what kind of authentication are we talking about? basic auth? OAuth? SAML? Does it even matter?
- what about authorization while we're here?
- if we're talking about auth, should we also talk about other cross cutting concerns?
For now, I don't want to go there with this repo and this blog post. However, I see how this is a legitimate need and I might come up with something in the future if I can find the time.
To address your immediate issue (and maybe this helps others who might stumble across this issue in the future):
Testing authentication is a matter of picking the right layer for your tests and asserting that you see the right behavior. A controller might return a 403
for a logged out user but a 200
for a logged in user. The response body might change. Your code might utilize Spring Security's automagic to handle authentication, or it might be much more explicit by passing a User
kind of object to those methods that do something for a given user.
For all things regarding your controllers, @WithMockUser
is a good start. It allows you to act on behalf of a mocked user as part of your integration test (whether that test's a WebMvcTest
that only spins up your controller layer or whether that test's a full-blown SpringBootTest
doesn't matter.
For your services and repositories, you might not even need this kind of annotation magic if you make your method signatures more explicit by passing a Principal
(or your own representation of a User
) object into your functions that rely on that information to perform any logic. This would allow you to simply unit test that function by passing in User
/Principle
objects with the right (or wrong) permissions, etc.