How to create session in Spring Junit

19.8k Views Asked by At

I have such layers:

Spring Controller -> Services layer -> Dao Layer (JPA).

I want to write test cases of services and controller. In the other Junit will invoke controller, controller will invoke services, service layer gets database information and etc..

In this case I do not want mocking, I want just to write junit test case (I must invoke service and service must get real data from database).

I have only one problem, service layer get's user id from session. I get session with autowired annotation. How can I create fake session during test cases?

p.s I think mock is not for me... because I do not wont to mock my service, I want to create real invoke of controller with real db data...

4

There are 4 best solutions below

0
On BEST ANSWER

We can do with mock. Here is sample of code.

private MockMvc mockMvc;

        @Autowired
        private FilterChainProxy springSecurityFilterChain;

        @Autowired
        private WebApplicationContext wac;

        protected MockHttpSession session;

        protected MockHttpServletRequest request;

        @Before
        public void setup() {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilters(this.springSecurityFilterChain).build();
        }

        @Test
        void test(){
        // I log in and then returns session 
        HttpSession session = mockMvc.perform(post("/j_spring_security_check").param("NAME", user).param("PASSWORD", pass))
                    .andDo(print()).andExpect(status().isMovedTemporarily()).andReturn().getRequest().getSession();
        }

Also we can do with this way, you can just to call startSession() method, and there will be "current" session returned.

protected void startSession() {
        session = new MockHttpSession();
    }

    protected void endSession() {
        session.clearAttributes();
        session = null;
    }

    // we can create request too, just simple way
    protected void startRequest() {
        request = new MockHttpServletRequest();
        request.setSession(session);
        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
    }
3
On
0
On

One option would be to inject the user ID (not the HttpSession) into your service component using a SpEL expression. To achieve proper run-time behavior, you must make sure your service component is an AOP-scoped proxy.

Take a look at the "Testing request and session scoped beans" section of the Spring reference manual for further information.

Regards,

Sam (spring-test component lead)

0
On

I wrote the following function to create "real" sessions when using a mongo session store.

private Session generateMongoHttpSession(final Role role, final Permission... permissions) {
  final Set<GrantedAuthority> authorities =
    role.getPermissions()
        .stream()
        .map(p -> new SimpleGrantedAuthority(p.toString()))
        .collect(Collectors.toSet());

  Arrays.stream(permissions)
    .forEach(p -> authorities.add(new SimpleGrantedAuthority(p.toString())));

  final UserDetails userDetails =
    new org.springframework.security.core.userdetails.User(
        "test-user-name", "test-password", true, true, true, true, authorities);

  final Authentication authentication =
    new UsernamePasswordAuthenticationToken(
        userDetails, userDetails.getPassword(), userDetails.getAuthorities());

  final UsernamePasswordAuthenticationToken authenticationToken =
    new UsernamePasswordAuthenticationToken(
          userDetails, authentication.getCredentials(), userDetails.getAuthorities());
  authenticationToken.setDetails(authentication.getDetails());

  final SecurityContextImpl context = new SecurityContextImpl();
  context.setAuthentication(authentication);

  final MongoExpiringSession session = mongoOperationsSessionRepository.createSession();
  session.setAttribute("SPRING_SECURITY_CONTEXT", context);
  session.setAttribute("sessionId", session.getId());
  mongoOperationsSessionRepository.save(session);

  return session;
}