Hello I set up a basic Api Test like below:
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@ActiveProfiles("test")
public abstract class BaseMockMvcSpec {
public static Logger log = LoggerFactory.getLogger(BaseMockMvcSpec.class);
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mvc;
@Autowired
FilterChainProxy springSecurityFilterChain;
@Autowired
UserRepository users;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
CustomClientDetailsService clientDetialsService;
@Mock SecurityContext mockSecurityContext;
@Before
public void setUp() {
RestAssuredMockMvc.standaloneSetup(new AccountDetailsController());
mvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity(springSecurityFilterChain))
.build();
BaseClientDetails testClient = new ClientBuilder("testclient")
.secret("testclientsecret")
.authorizedGrantTypes("password")
.scopes("read", "wirte")
.autoApprove(true)
.build();
clientDetialsService.addClient(testClient);
User user = createDefaultUser("testuser", passwordEncoder.encode("testpassword"), "max", "Mustermann", new Email("test@lokata.de"));
users.deleteAll();
users.save(user);
log.info("setup BaseMockMvcSpec");
}
public String oauth(){
String token = "notValidToken";
try {
token = validAccessToken();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "Bearer " + token;
}
private String validAccessToken() throws Exception {
String username = "testuser";
String password = "testpassword";
MockHttpServletResponse response = mvc
.perform(post("/oauth/token")
.header("Authorization", "Basic "
+ new String(Base64Utils.encode(("testclient:testclientsecret")
.getBytes())))
.param("username", username)
.param("password", password)
.param("grant_type", "password"))
.andDo(print())
.andReturn().getResponse();
return new ObjectMapper()
.readValue(response.getContentAsByteArray(), OAuthToken.class)
.accessToken;
}
@JsonIgnoreProperties(ignoreUnknown = true)
private static class OAuthToken {
@JsonProperty("access_token")
public String accessToken;
}
}
I get the following output of the Test run:
2017-06-27 01:36:23.379 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Neither @ContextConfiguration nor @ContextHierarchy found for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest], using SpringBootContextLoader
2017-06-27 01:36:23.379 INFO 47446 --- [ Test worker] o.s.t.c.support.AbstractContextLoader : Could not detect default resource locations for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2017-06-27 01:36:23.379 INFO 47446 --- [ Test worker] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest]: OauthserviceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
2017-06-27 01:36:23.383 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration de.example.microservice.authservice.AuthserverApplication for test class de.example.microservice.authservice.verifier.tests.OauthserviceTest
2017-06-27 01:36:23.385 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener]
2017-06-27 01:36:23.386 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@2efec58d, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@65dbe1b, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@4d31ce57, org.springframework.test.context.support.DirtiesContextTestExecutionListener@750239e7, org.springframework.test.context.transaction.TransactionalTestExecutionListener@2d885867, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@464e86ab, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener@54eab43, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@6167770c, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@ec35027, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@3c0ae48a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@4cee44fb, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@166b957d, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@2bdadff]
2017-06-27 01:36:23.459 INFO 47446 --- [ Test worker] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring FrameworkServlet ''
2017-06-27 01:36:23.459 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started
2017-06-27 01:36:23.462 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 3 ms
2017-06-27 01:36:23.540 INFO 47446 --- [ Test worker] d.l.m.authservice.BaseMockMvcSpec : setup BaseMockMvcSpec
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token']
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : matched
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@79e774c0
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'GET /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/logout'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'PUT /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'DELETE /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 5 of 12 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'testclient'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e2b6867: Principal: org.springframework.security.core.userdetails.User@81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.AnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e2b6867: Principal: org.springframework.security.core.userdetails.User@81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@b7217c5
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e2b6867: Principal: org.springframework.security.core.userdetails.User@81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6b9626fc, returned: 1
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token reached end of additional filter chain; proceeding with original chain
2017-06-27 01:36:23.569 DEBUG 47446 --- [ Test worker] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/token
2017-06-27 01:36:23.569 DEBUG 47446 --- [ Test worker] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException]
2017-06-27 01:36:23.572 DEBUG 47446 --- [ Test worker] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: testclient
2017-06-27 01:36:23.572 DEBUG 47446 --- [ Test worker] o.s.s.authentication.ProviderManager : Authentication attempt using de.example.microservice.authservice.authentication.behavior.CustomAuthenticationProvider
2017-06-27 01:36:23.656 DEBUG 47446 --- [ Test worker] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2017-06-27 01:36:23.656 DEBUG 47446 --- [ Test worker] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
MockHttpServletRequest:
HTTP Method = POST
Request URI = /oauth/token
Parameters = {username=[testuser], password=[testpassword], grant_type=[password]}
Headers = {Authorization=[Basic dGVzdGNsaWVudDp0ZXN0Y2xpZW50c2VjcmV0]}
Handler:
Type = org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
Method = public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY], Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOiJmZjgwODA4MTVjZTZjMzBkMDE1Y2U2YzM2MmYzMDAyNyIsInVzZXJfbmFtZSI6InRlc3R1c2VyIiwic2NvcGUiOlsicmVhZCIsIndpcnRlIl0sIm9yZ2FuaXNhdGlvbiI6ImRlZmF1bHQiLCJleHAiOjE0OTg1NjMzODMsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiJlZGRmZWUyZS01NTU2LTQ1YWItOTIwMC02NThiM2FkNmRiNWYiLCJjbGllbnRfaWQiOiJ0ZXN0Y2xpZW50In0.bL9mLo1Ao6oUBA3BxrIIEWTEXVlTml5GqeoeAKqA_pXDFBn-gIRafRH8ji3BceTg-cjih_-cYYAbRiVmjsCAUd0nE-chwIwhwPp2WSAfgz9OHd531VsDOX7l8-vkR_BUKY5X02pIf2W9ZlsqCZ-isarRzWI_AQpNgqwoIDcICDeuB1lNWqkwtwmI_f0cF3u0J2FuQBvye3Sj4xXmrQU0awCj0F891v6bPqkM0Wc5G6i8Mm-n-OnRbMqcckfxAsSqtDEYrDe3T6otFfREZ6AYTefMzQWYbYXDK0tCkohH46hNmKlbrXNWUrnwYLDeCZyOGm8bCrOihDzjYJgw5RshKQ","token_type":"bearer","expires_in":43199,"scope":"read wirte","accountId":"ff8080815ce6c30d015ce6c362f30027","organisation":"default","jti":"eddfee2e-5556-45ab-9200-658b3ad6db5f"}
Forwarded URL = null
Redirected URL = null
Cookies = []
2017-06-27 01:36:23.684 INFO 47446 --- [ Test worker] ilder$StaticRequestMappingHandlerMapping : Mapped "{[/api/me],methods=[GET],produces=[application/json;charset=UTF-8]}" onto public java.security.Principal de.example.microservice.authservice.rest.behavior.AccountDetailsController.user(java.security.Principal)
2017-06-27 01:36:23.692 INFO 47446 --- [ Test worker] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext@734a6c74
2017-06-27 01:36:23.696 INFO 47446 --- [ Test worker] o.s.mock.web.MockServletContext : Initializing Spring FrameworkServlet ''
2017-06-27 01:36:23.696 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started
2017-06-27 01:36:23.696 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 0 ms
The TestException is
java.lang.IllegalArgumentException: json string can not be null or empty
at com.jayway.jsonpath.internal.Utils.notEmpty(Utils.java:386)
at com.jayway.jsonpath.internal.JsonContext.parse(JsonContext.java:81)
at com.jayway.jsonpath.JsonPath.parse(JsonPath.java:596)
at de.example.microservice.authservice.verifier.tests.OauthserviceTest.validate_shouldReturnAccountDetails(OauthserviceTest.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method
I guess the autogenerated Test is not executed but didn't know how to debug them. The get Oauth2 token works perfect and also the execution of the oath() method in the verifier Class.
I ended up with the following test setup:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ContextConfiguration
@WebAppConfiguration
@ActiveProfiles("test")
public abstract class UserDetailsControllerTestBase {
public static Logger log = LoggerFactory.getLogger(UserDetailsControllerTestBase.class);
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mvc;
@Autowired
FilterChainProxy springSecurityFilterChain;
@Mock SecurityContext mockSecurityContext;
@Before
public void setUp() {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
//RestAssured.baseURI="http://localhost";
//RestAssured.port = port;
mvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.defaultRequest(get("/api/me").with(user("user").roles("USER")))
.apply(springSecurity(springSecurityFilterChain))
.build();
RestAssuredMockMvc.mockMvc(mvc);
}
public String oauth(){
String token = "notValidToken";
try {
token = validAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
return "Bearer " + token;
}
public void assertIsNull(Object value){
assertThat(value, is(nullValue()));
}
private String validAccessToken() throws Exception {
String username = "user";
String password = "password";
MockHttpServletResponse response = mvc
.perform(post("/oauth/token")
.header("Authorization", "Basic "
+ new String(Base64Utils.encode(("client:clientsecret")
.getBytes())))
.param("username", username)
.param("password", password)
.param("grant_type", "password"))
.andDo(print())
.andReturn().getResponse();
return new ObjectMapper()
.readValue(response.getContentAsByteArray(), OAuthToken.class)
.accessToken;
}
@JsonIgnoreProperties(ignoreUnknown = true)
private static class OAuthToken {
@JsonProperty("access_token")
public String accessToken;
}
}
Check out the example Solution Repository for more details