4

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...

DwB
  • 37,124
  • 11
  • 56
  • 82
grep
  • 5,465
  • 12
  • 60
  • 112

4 Answers4

6

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));
    }
grep
  • 5,465
  • 12
  • 60
  • 112
2

You can use MockHttpSession: http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/mock/web/MockHttpSession.html

More info here: Spring mvc 3.1 integration tests with session support

Community
  • 1
  • 1
kmandov
  • 3,130
  • 16
  • 15
  • I do not wont mock. Because then I invoke this.mockMvc.perform(my controller), mock does not invoke my service layer. this is my proble,m – grep Nov 24 '14 at 11:11
  • I mean this problem when I use mock, so i do not wont mock: http://stackoverflow.com/questions/26508628/how-to-call-springs-service-method-from-controller-junit – grep Nov 24 '14 at 11:16
  • If you're storing the user id as an attribute on the session, you can set that on `MockHttpSession` as well. Then, when your code uses that object, it will return whatever value you want it to. – Foxsly Nov 24 '14 at 16:45
1

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)

Sam Brannen
  • 29,611
  • 5
  • 104
  • 136
0

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;
}