#WithMockUser doesn't pick Spring Security auth credentials - spring

I have setup basic authentication in my controller with Spring Security in the classic way as follows:
#EnableWebSecurity
#EnableGlobalMethodSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("user").roles("USER")
.and()
.withUser("admin").password("admin").roles("USER", "ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(....);
}
}
When it comes to the point of testing, I am using #WithMockUser to annotate my tests. A test might look like this for GET:
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = SomeController.class)
public class SomeControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void test1() {
mockMvc.perform(get(...)).andExpect(...);
}
or like this for POST:
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = SomeController.class)
public class SomeControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void test1() {
mockMvc.perform(post(...)).andExpect(...);
}
then something unexpected happens:
when a test method is not annotated with #WithMockUser, it fails because of 401 status (Unauthorized) which is reasonable, because no basic authentication has been fullfilled
when a test method is simply annotated with an empty #WithMockUser without specifying ANY credentials, it starts passing, which is not reasonable, because I did not provide the correct data for authentication (rather I left them empty)
at this point a test method is passing also when filling in some correct credentials like in #WithMockUser(username = "user", password = "user", roles = "USER")
QUESTION: what's going on? How to fix this misbehaviour?
Looks like Spring Security is activated, however my testing is not using the authentication that I would expect to be used. Do I have to mock the authentication data myself?
EDIT The full configure method is the following
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(URL1).hasAnyRole(ROLE_ADMIN)
.antMatchers(URL2).hasAnyRole(ROLE_USER)
.antMatchers(URL3).permitAll()
.and()
.httpBasic()
.and()
.csrf().disable();
}

There are two reasons behind this behavior:
#WithMockUser annotation is not intended to execute authentication. It creates a user which is authenticated already. By default his credentials are user : password
#WebMvcTest does not execute MySecurityConfig.java. This annotation creates Spring mockMvc object with Security defaults for testing. Those security defaults are applied by org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration
You can double check this by putting break points on MySecurityConfig methods and rerunning your test in debug mode. Break points are not hit.
Solving issue 1
Simply change your approach to what #WithMockUser annotation does. It gives already logged-in user. It is still possible to test urls security and roles configuration with specifying concrete username, password and roles.
Solving issue 2
Create a base class for all Integration tests. It will configure mockMvc with Spring Security applied. Also note #SpringBootTest annotation. Now test will use MySecurityConfig.java
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
#RunWith(SpringRunner.class)
#SpringBootTest
public abstract class IT {
#Autowired
protected WebApplicationContext wac;
#Autowired
private FilterChainProxy springSecurityFilterChain;
protected MockMvc mockMvc;
#Before
public void applySecurity() {
this.mockMvc = webAppContextSetup(wac)
.apply(springSecurity(springSecurityFilterChain))
.build();
}
}
Rewrite the test like this. Assuming you use http basic authentication. Credentials are provided inside the test. Note: no mock user annotation.
package com.example.demo;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import org.junit.Test;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
public class SomeControllerIT extends IT {
#Test
public void test1() throws Exception {
mockMvc.perform(get("/some")
.with(httpBasic("user", "user")))
.andExpect(MockMvcResultMatchers.content().string("hello"));
}
}

Here is how you can run your mockMVC tests with your configuration of spring security: for the USER role...
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = SomeController.class)
public class SomeControllerTest {
#Autowired
private WebApplicationContext context;
#Autowired
private MockMvc mockMvc;
#Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.defaultRequest(get("/")
.with(user("user").password("password").roles("USER")))
.apply(springSecurity())
.build();
}
#Test
public void test1() {
mockMvc.perform(get(...)).andExpect(...);
}
}
after making this change your GET tests should now work.
since spring security provides cross site request forgery protection for http requests such as POST and DELETE, you need to run these particular tests with crsf()
#Test
public void shouldPost() {
mockMvc.perform(post(...)).with(csrf().asHeader())
.andExpect(...);
}

I faced the same issue. I could resolve it by with the #WithMockUser annotation with authorities specified.
#Test
#DisplayName("Should create and return the student")
#WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
public void should_create_student() throws Exception {
mockMvc.perform(post(...)).andExpect(...);
}

For information, this code has allowed me to successfully run a credentialed test, with credentials extracted from the application.properties file, without using an #WithMockUser annotation.
#Autowired
MockMvc mvc;
#Autowired
private WebApplicationContext context;
#MockBean
BookRepository bookRepository;
#Test
public void testFindAll() throws Exception {
mvc = MockMvcBuilders.webAppContextSetup(context).build();
this.mvc.perform(get("/books").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}

Related

Set authentication for Integration test of secured Controller

I cannot set authentication for my integration test of rest controller. Controller's method looks like this:
#RestController
#RequestMapping(BASE_URL)
#RequiredArgsConstructor
public class EventController {
public static final String BASE_URL = "/api/event";
#PostMapping
#PreAuthorize("hasRole('USER')")
public void createEvent() {
System.out.println("I am in controller");
}
}
and here is my test:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class EventControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext context;
#BeforeEach
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
#Test
void create() throws Exception {
this.mockMvc.perform(post(EventController.BASE_URL)
.with(authentication(new UsernamePasswordAuthenticationToken(
new MyPrincipal(100, "denis"),
null,
Collections.singletonList(new SimpleGrantedAuthority("USER"))
)))
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"));
}
My test always failed due to status 401 so my mocked authentication doesn't work. Can you tell me how to fix it? Thank you in advice.
The easiest way to test secured requests is to use #WithMockUser(A_ROLE)
so your test could look like
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
#SpringBootTest
#AutoConfigureMockMvc
class EventControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
#WithMockUser("USER")
void create() throws Exception {
this.mockMvc.perform(post(EventController.BASE_URL)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"));
}
}
Some remarks:
your test expects a result, so adopt your controller or test
#PostMapping
#PreAuthorize("hasRole('ROLE_USER')")
public ResponseEntity<String> createEvent() {
String result = "I am in controller";
System.out.println(result);
return ResponseEntity.ok().body(result);
}
you are doing/testing a POST so make sure that in your security configuration you do http.csrf().disable()....
or provide a csrf-token in your test
this.mockMvc.perform(post(EventController.BASE_URL)
.with(SecurityMockMvcRequestPostProcessors.csrf()) // provide a csrf-token
....
'

Mock Spring's remote JWT service

I'm currently using RemoteTokenServices class:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Value("${auth-server.url}")
private String authEndpoint;
#Value("${security.oauth2.client.client-id}")
private String clientId;
#Value("${security.oauth2.client.client-secret}")
private String clientSecret;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("ms/legacy");
}
#Bean
public ResourceServerTokenServices tokenService() {
RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setClientId(clientId);
tokenServices.setClientSecret(clientSecret);
tokenServices.setCheckTokenEndpointUrl(authEndpoint + "/uaa/oauth/check_token");
return tokenServices;
}
}
I want to be able to mock this easily and properly for all my endpoints integration tests, knowing that:
the JWT is decoded in a OncePerRequestFilter to get some crucial info
I'm not interested in testing auth failures (well I am but that's not something that we want to do on each endpoint)
Is there a standard way to:
Produce a JWT token by hand ?
Mock all token service accesses easily ?
The expected result would be that I can write an endpoint test with only a few extra lines to setup the right JWT in the request, and the token service would agree on its validity dumbly.
Given that we don't want to test security at all, the best solution for this kind of case is to:
use standard Spring tests security management #WithMockUser along with MockMvc
adapt the ResourceServerConfigurerAdapter for tests:
create a base class that hosts all the config except for tokens
create an inheriting class for non-tests profiles (#ActiveProfiles("!test")) that hosts the token specific configuration
create an inheriting class for test profile that deactivates the remote token check (security.stateless(false);)
make the test classes use test profile
inject the proper token-extracted infos at the right time in tests
Here is how it was implemented in practice:
Base ResourceServerConfigurerAdapter so that the configuration has a major common part between tests and non-tests contexts:
public class BaseResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("ms/legacy");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().cors().disable().csrf().disable().httpBasic().disable()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.accessDeniedHandler(
(request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED));
}
}
Its implementation outside for non-test:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
#Profile("!test")
public class ResourceServerConfiguration extends BaseResourceServerConfiguration {
#Value("${auth-server.url}")
private String authEndpoint;
#Value("${security.oauth2.client.client-id}")
private String clientId;
#Value("${security.oauth2.client.client-secret}")
private String clientSecret;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("ms/legacy");
}
#Bean
public ResourceServerTokenServices tokenService() {
RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setClientId(clientId);
tokenServices.setClientSecret(clientSecret);
tokenServices.setCheckTokenEndpointUrl(authEndpoint + "/uaa/oauth/check_token");
return tokenServices;
}
}
And for tests:
#Configuration
#EnableResourceServer
#ActiveProfiles("test")
public class TestResourceServerConfigurerAdapter extends BaseResourceServerConfiguration {
#Override
public void configure(ResourceServerSecurityConfigurer security) throws Exception {
super.configure(security);
// Using OAuth with distant authorization service, stateless implies that the request tokens
// are verified each time against this service. In test, we don't want that because we need
// properly isolated tests. Setting this implies that the security is checked only locally
// and allows us to mock it with #WithMockUser, #AutoConfigureMockMvc and autowired MockMVC
security.stateless(false);
}
}
Inject token specific info with a request filter for tests:
#Component
#ActiveProfiles("test")
public class TestRequestFilter extends OncePerRequestFilter {
private Optional<InfoConf> nextInfoConf = Optional.empty();
// Request info is our request-scoped bean that holds JWT info
#Autowired
private RequestInfo info;
#Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
if (nextInfoConf.isPresent()) {
info.setInfoConf(nextInfoConf.get());
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
public void setNextInfoConf(InfoConf nextInfoConf) {
this.nextInfoConf = Optional.of(nextInfoConf);
}
public void clearNextInfoConf() {
nextInfoConf = Optional.empty();
}
}
And of course make the JWT parsing do nothing when there's no JWT.
We also wrote a small utility component to create the relevant info to inject.
A typical integration test will be like this:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#ActiveProfiles("test")
public class TestClass {
#Autowired
protected MockMvc mockMvc;
#Before
public void before() {
// Create an user in DB
// Inject the related information in our filter
}
#After
public void after() {
// Cleanup both in DB and filter
}
#Test
#WithMockUser
public void testThing() throws Exception {
// Use MockMVC
}
}
Another solution is to indeed mock the ResourceServerTokenServices but in fact it's much more a pain to build proper tokens, and using Spring's standard security mock seems much more appropriate.

How enable/disable #EnableGlobalMethodSecurity for #Service methods for testing scenario

I am working with Spring Framework and Spring Security
About Testing
For a set of Test classes for #Controller with security, .apply(springSecurity() and #WithUserDetails(value="something") are used
#Before
public void setUp(){
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.apply(springSecurity())// <---
.build();
}
For other set of Test classes for #Controller without security, therefore .apply(springSecurity()) and #WithUserDetails(value="something") are not used.
#Before
public void setUp(){
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.build();
}
Until here all about for #Controller with and without security work fine.
The problem is for the #Service, when #EnableGlobalMethodSecurity is defined and the #Service methods are annotated with #PreAuthorize("hasRole('ROLE_ADMIN')"), all the other Test classes for #Service where security is not required fail now with:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException:
An Authentication object was not found in the SecurityContext
Of course it because the #Test methods do not use #WithUserDetails(value="something")
Thus, practically .apply(springSecurity()) does the job, but it for a Web environment through MockMvcBuilders.webAppContextSetup(webApplicationContext)
But for the server side, where security is not needed, I have:
#Transactional
#RunWith(Parameterized.class)
#ContextConfiguration(classes={RootApplicationContext.class})
#ActiveProfiles(resolver=TestActiveProfilesResolver.class)
#TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplTest {
private static final Logger logger = LoggerFactory.getLogger(PersonaServiceImplTest.class.getSimpleName());
#ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
#Autowired
private Environment environment;
...
Thus MockMvcBuilders.webAppContextSetup(webApplicationContext) has no sense to be used. What is the best way to resolve this?
You can use #WithUserDetails and #WithMockUser to test method security as well.
For the tests to pick up on method security, you need to include the class annotated with #EnableGlobalMethodSecurity in the component classes used for loading the ApplicationContext.
For example, if the configuration class SecurityConfig is annotated with EnableGlobalMethodSecurity
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig { }
And the Service MessageService has a method using #PreAuthorize.
#Service
public class MessageService {
public String getHelloMessage() {
return "Hello!";
}
#PreAuthorize("hasRole('ADMIN')")
public String getGoodbyeMessage() {
return "Goodbye!";
}
}
Then you need to include both of those classes in the MessageServiceTest and you can use the security testing annotations.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = {SecurityConfig.class, MessageService.class})
public class MessageServiceTest {
#Autowired
MessageService messageService;
#Test
public void helloMessageReturnsHello() {
assertThat(messageService.getHelloMessage()).isEqualTo("Hello!");
}
#Test(expected = AuthenticationCredentialsNotFoundException.class)
public void goodbyeMessageWithoutUserThrowsException() {
messageService.getGoodbyeMessage();
}
#WithMockUser(roles = "ADMIN")
#Test
public void goodbyeMessageWithAdminReturnsGoodbye() {
assertThat(messageService.getGoodbyeMessage()).isEqualTo("Goodbye!");
}
}

Spring Boot Test MockMvc perform post - Not working

I'm trying to make a Integration test using the Spring Boot but the post request is not working. The method saveClientePessoaFisica is never called and do not return any kind of error! I just tried to make other tests using a get method and it works properly.
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
#ActiveProfiles("dev")
public class ClienteControllerIT {
#Autowired
private MockMvc mvc;
#Test
public void nao_deve_permitir_salvar_cliente_pf_com_nome_cpf_duplicado() throws Exception {
this.mvc.perform(post("/api/cliente/pessoafisica/post")
.contentType(MediaType.APPLICATION_JSON)
.content("teste")
.andExpect(status().is2xxSuccessful());
}
}
#RestController
#RequestMapping(path = "/api/cliente")
public class ClienteController {
#Autowired
private PessoaFisicaService pessoaFisicaService;
#PostMapping(path = "/pessoafisica/post", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> saveClientePessoaFisica(#RequestBody PessoaFisica pessoaFisica) throws Exception {
this.pessoaFisicaService.save(pessoaFisica);
return new ResponseEntity<Void>(HttpStatus.CREATED);
}
}
Your content "teste" is no valid JSON. When I am using your code, I'm getting a JsonParseException complaining about that (By the way, there is a parenthese missing after content("teste") ). Also helpful is using andDo(print()) which will give you the request and response in more detail:
#Test
public void nao_deve_permitir_salvar_cliente_pf_com_nome_cpf_duplicado() throws Exception {
this.mvc.perform(post("/api/cliente/pessoafisica/post")
.contentType(MediaType.APPLICATION_JSON)
.content("teste"))
.andDo(print())
.andExpect(status().is2xxSuccessful());
}
Some things to look for :
Enable logging in your mockmvc
Enable your mockmvc properly
When using spring security, initialise it in mockmvc
When using spring security / CSRF / HTTP POST , pass a csrf in your mockmvc
Enable debug logging
Like this :
logging:
level:
org.springframework.web: DEBUG
org.springframework.security: DEBUG
Working test :
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
#AutoConfigureMockMvc
public class MockMvcTest {
#Autowired
protected ObjectMapper objectMapper;
#Autowired
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void init() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build();
}
#Test
public void adminCanCreateOrganization() throws Exception {
this.mockMvc.perform(post("/organizations")
.with(user("admin1").roles("ADMIN"))
.with(csrf())
.contentType(APPLICATION_JSON)
.content(organizationPayload("org1"))
.accept(APPLICATION_JSON))
.andDo(print())
.andExpect(status().isCreated());
}
}

how to use jmockit with spring's mockmvc to test controller

I want to use mockmvc to test controller which is recommended by Spring. But, I also have to use jmockit to mock the dependences.
The problem is that jmockit can't do well with mockmvc, whether the standaloneSetup() or the webAppContextSetup().
Another mocking tool named Mockito is well done with this problem, but it has a lot limits in mocking dependencies.
So, anybody has the experience or idea, please tell me. Thank you very much.
The example code is as following:
The first is the Mockito with Spring's MockMvc to unit test controller. This runs well.
public class TestControllerTest {
#InjectMocks
private LoginController loginController;
#Mock
private LoginService loginService;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(loginController).build();
}
#Test
public void testLogin() throws Exception {
when(loginService.login()).thenReturn(false);
this.mockMvc.perform(get("/login"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("goodbyeworld"))
.andReturn();
}
}
Secondly, the jmockit is as following. Unfortunately, the loginController is null at the setup method. And, if i just invoke the loginController.xxx() in the #Tested method is fine. I think this shows that loginController is instantiated before #Tested method but after #Before method.
public class TestControllerTest2 {
#Tested
private LoginController loginController;
#Injectable
private LoginService loginService;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.standaloneSetup(loginController).build();
}
#Test
public void testLogin() throws Exception {
new Expectations() {{
loginService.login(); result = false;
}};
this.mockMvc.perform(get("/login"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("goodbyeworld"))
.andReturn();
}
}
So, how can this problem be solved? jmockit's handful init method? any possible?
Differently from Mockito's #InjectMocks, JMockit's #Tested fields get created only after the execution of any #Before methods. This happens because of the support for mock parameters in test methods, which doesn't exist in Mockito. Arguably, tested fields should be set early, together with mock fields, so this may change in a future version of JMockit.
Anyway, solutions for the problem as it stands today are:
Do not use #Tested; instead, instantiate and inject the object under test manually in the #Before method.
Use #Tested, but avoid #Before methods which depend on tested fields. In the example test, the MockMvc object could be created in each test method by calling a MockMvc mockMvc() { return MockMvcBuilders... } method.
I have faced similar problem recently, and I have found a little bit of graceful solution:
#Tested(availableDuringSetup=true)
NotificationController notificationController;
#Injectable
NotificationService notificationService;
private MockMvc mockMvc;
#Before
public void init() {
this.mockMvc = MockMvcBuilders.standaloneSetup(notificationController).build();
}
boolean availableDuringSetup attribute for #Tested annotation is the solution :)
Hope that helps,
The problem is jmockit can't do well with mockmvc
I find that JMockit and Spring's MockMvc do play together well enough. I have successfully used the webAppContextSetup in my case. Here is an example which may not compile even, but could be a useful guide to get you started..
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import mockit.*;
import org.junit.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
import some.package.Account;
import some.package.Collaborator;
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
#WebAppConfiguration
#ContextConfiguration(locations = { "classpath:/context/example1.xml", "classpath:/context/example2.xml" })
public class AccountControllerIntegrationTest {
private static final String PATH_TO_ACCOUNT = "/accounts/some_account";
private String exampleAccountJson = "{\"account\":\"Sample\",\"active\":true}";
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Mocked
private Account mockAccount;
#Mocked
private Collaborator mockCollaborator;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
#Test
public void should_delete_account() throws Exception {
new Expectations() {{
mockAccount.getSomethingWhichReallyShouldNotBeExposed(); result = mockCollaborator;
mockCollaborator.getSomething(); result = "whatever";
}};
mockMvc.perform(delete(PATH_TO_ACCOUNT)).andExpect(status().isOk());
}
#Test
public void should_add_account() throws Exception {
new NonStrictExpectations() {{
mockAccount.getSomethingWhichReallyShouldNotBeExposed(); result = mockCollaborator;
mockCollaborator.getSomething(); result = "whatever";
}};
mockMvc.perform(put(PATH_TO_ACCOUNT).contentType(MediaType.APPLICATION_JSON).content(exampleAccountJson)).andExpect(status().isOk());
}
}
Hope it can help you--good luck!

Resources