Home > database >  wicket 9: unit testing mockito httpSession
wicket 9: unit testing mockito httpSession

Time:12-08

A Situation

I'm using wicket 9 for a web gui development. And now I'm trying to do some junit testing by mocking (mockito) methods that are not essential. One of those methods is

httpSession.getAttribute("loginName");

which gets called like this:

public class MyPanel {
         ...

     SecureWebSession session = (SecureWebSession) getSession(); <--returns a SecuredWebSession
     Label username = new Label("loginName", session.getLoginName()); <-- NullPointerException
        ...
}

Obviously, something is not right with how I'm mocking things. I expect it to return test, but all I get at all times is a NullPointerException.

My question is how can I bypass session.getLoginName() so, that the call would return a login name test?

How to mock httpSession while testing wicket application?

Details

I have a securedWebSession class

package com.my.app.application;

import com.my.app.service.signOnService;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.injection.Injector;
import org.apache.wicket.request.Request;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;

public class SecureWebSession extends AuthenticatedWebSession {

    @SpringBean(name = "authenticationManager")
    private AuthenticationManager authenticationManager;

    @SpringBean(name = "signOnService")
    private SignOnService signOnService;

    private final HttpSession httpSession;

    private final Request request;

    public SecureWebSession(Request request) {
        super(request);
        this.request = request;
        //******************THIS I CANNOT BYPASS***************************************START
        this.httpSession = ((HttpServletRequest) request.getContainerRequest())
                .getSession(false);
        //******************THIS I CANNOT BYPASS******ALLWAYS RETURNS NULL*************END
        
        Injector.get().inject(this);
    }

    @Override
    public boolean authenticate(String username, String password) {
        return true;
    }

    private boolean hasSignedIn(Authentication authentication) {
        return authentication.isAuthenticated();
    }

    @Override
    public Roles getRoles() {
        Roles roles = new Roles();
        roles.add("SUPER_ADMIN");
        return roles;
    }

    public String getLoginName() {
     ********RETURNS NULL.getAttribute("loginName")******
        return (String) httpSession.getAttribute("loginName");
    }
}

I have a test setup as following

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {
  MyWicketApplication.class
})
public class ApplicationTest {

  private WicketTester tester;

  private final WebApplication webApplication;

  @Autowired
  public SecuredWicketGuiApplicationTest(WebApplication application) {
    this.webApplication = application;
  }

  @BeforeEach
  public void setUp() {

    //**** ** * WORKS ** ** ** **
    // when authenticated is given
    Authentication authentication = Mockito.mock(Authentication.class);
    SecurityContext securityContext = Mockito.mock(SecurityContext.class);
    Mockito.when(securityContext.getAuthentication()).thenReturn(authentication);
    Mockito.when(authentication.isAuthenticated()).thenReturn(true);
    SecurityContextHolder.setContext(securityContext); 
    //** ** ** ** ** ** ** ** ** *

    // and secured session is provided
    SecureWebSession secureWebSession = Mockito.mock(SecureWebSession.class);

    //**** ** * WORKS ** ** ** **
    // and a superuser role is given
    Roles roles = new Roles();
    roles.add("SUPER_ADMIN");
    Mockito.when(secureWebSession.getRoles()).thenReturn(roles); 
    //** ** ** ** ** ** ** ** **

    // and session has loginName attribute
    HttpSession session = Mockito.mock(HttpSession.class);
    Mockito.when(session.getAttribute("loginName")).thenReturn("test");

    HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
    Mockito.when(request.getSession()).thenReturn(session);

    tester = new WicketTester(webApplication);

    MockHttpSession mockHttpSession = new MockHttpSession(null);
    mockHttpSession.setAttribute("loginName", "test");

    // and a requested initiated for a given session
    MockHttpServletRequest mockedRequest = new MockHttpServletRequest(
      tester.getApplication(), mockHttpSession, null) {
      @Override
      public HttpSession getSession(boolean createNew) {
        return mockHttpSession;
      }

      @Override
      public HttpSession getSession() {
        return mockHttpSession;
      }
    };

    // and a session object is created with a loginName attribute test
    tester.getRequest().getSession()
      .setAttribute("loginName", "test");

    tester.setRequest(mockedRequest);
  }

  @Test
  public void HomePage_Renders_Successfully() {
    // then start and render the homePage page
    tester.startPage(HomePage.class);
    // assert rendered HomePage component
    tester.assertRenderedPage(HomePage.class);
  }
}

when I try to execute this test I get stuck on

public class MyPanel {
     ...

 SecureWebSession session = (SecureWebSession) getSession(); <--returns a SecuredWebSession
 Label username = new Label("loginName", session.getLoginName()); <-- NullPointerException
    ...
}

Where method getLoginName is defined in securedWebSession

public String getLoginName() {
 ********RETURNS NULL.getAttribute("loginName")******
    return (String) httpSession.getAttribute("loginName");
}

CodePudding user response:

You create several objects via their constructors but they (most of them) are not used later. WicketTester uses the passed Application to find the others, i.e. it uses application#newSession() to create the Wicket Session, and application#newRequest() to create the Wicket Request. If you want to use mock versions of those then you need to create a custom MyTestWebApplication (that extends from MyWicketApplication), override these methods and set it up as a Spring bean.

WicketTester uses a new/fresh instance of MockHttpServletRequest for each request. You can get a reference to it via tester.getRequest() and call its #setAttibute()method before actually making the HTTP call (e.g. viaclickLink(), executeAjaxEvent()orstartPage()`).

So you could just use tester.getHttpSession().setAttribute(..., ...) before making the http call.

  • Related