калитка 9: модульное тестирование mockito HttpSession

#unit-testing #wicket

#модульное тестирование #калитка

Вопрос:

Ситуация

Я использую wicket 9 для разработки веб-графического интерфейса. И теперь я пытаюсь провести тестирование junit с помощью насмешливых (mockito) методов, которые не являются существенными. Одним из таких методов является

 httpSession.getAttribute("loginName");  

который называется так:

 public class MyPanel {  ...   SecureWebSession session = (SecureWebSession) getSession(); lt;--returns a SecuredWebSession  Label username = new Label("loginName", session.getLoginName()); lt;-- NullPointerException  ... }  

Очевидно, что-то не так с тем, как я издеваюсь над вещами. Я ожидаю, что он вернет тест, но все, что я всегда получаю, — это исключение NullPointerException.

Мой вопрос в том, как я могу обойти session.getLoginName (), чтобы вызов вернул тест имени входа?

Как имитировать HttpSession при тестировании приложения wicket?

Подробные сведения

У меня есть класс securedWebSession

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

У меня есть тестовая настройка, как показано ниже

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

когда я пытаюсь выполнить этот тест, я застреваю на

 public class MyPanel {  ...   SecureWebSession session = (SecureWebSession) getSession(); lt;--returns a SecuredWebSession  Label username = new Label("loginName", session.getLoginName()); lt;-- NullPointerException  ... }  

Где метод getLoginName определен в securedWebSession

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

Ответ №1:

Вы создаете несколько объектов с помощью их конструкторов, но они (большинство из них) позже не используются. WicketTester использует переданное приложение для поиска других, т. Е. Использует приложение#NewSession() для создания сеанса Калитки и приложение#newRequest() для создания запроса Калитки. Если вы хотите использовать макетные версии этих приложений, вам нужно создать пользовательское приложение MyTestWebApplication (которое распространяется на приложение MyWicketApplication), переопределить эти методы и настроить его как компонент Spring.

WicketTester использует новый/свежий экземпляр MockHttpServletRequest для каждого запроса. Вы можете получить ссылку на него через tester.getRequest() и вызвать его #setAttibute() method before actually making the HTTP call (e.g. via clickLink() , executeAjaxEvent() or StartPage()`).

Таким образом, вы можете просто использовать tester.getHttpSession().setAttribute(..., ...) его перед выполнением http-вызова.