【问题标题】:wicket 9: unit testing + mockito + httpSession检票口 9:单元测试 + mockito + httpSession
【发布时间】:2021-12-07 10:55:00
【问题描述】:

一种情况

我正在使用 wicket 9 进行 Web gui 开发。现在我正在尝试通过模拟(mockito)非必要方法来进行一些junit测试。其中一种方法是

httpSession.getAttribute("loginName");

这样调用:

public class MyPanel {
         ...

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

很明显,我嘲笑的方式有些不对劲。我希望它返回测试,但我得到的只是 NullPointerException。

我的问题是如何绕过 session.getLoginName() 以便调用返回 登录名测试?

如何在测试 wicket 应用程序时模拟 httpSession?

详情

我有一个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(); <--returns a SecuredWebSession
 Label username = new Label("loginName", session.getLoginName()); <-- NullPointerException
    ...
}

其中方法 getLoginName 在securedWebSession 中定义

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

【问题讨论】:

    标签: unit-testing wicket


    【解决方案1】:

    您通过它们的构造函数创建了多个对象,但它们(大多数)稍后不会使用。 WicketTester 使用传递的应用程序来查找其他应用程序,即它使用 application#newSession() 创建 Wicket 会话,并使用 application#newRequest() 创建 Wicket 请求。如果您想使用它们的模拟版本,那么您需要创建一个自定义 MyTestWebApplication(从 MyWicketApplication 扩展),覆盖这些方法并将其设置为 Spring bean。

    WicketTester 为每个请求使用一个新的/新鲜的 MockHttpServletRequest 实例。您可以通过tester.getRequest() 获取对它的引用并调用它的#setAttibute()method before actually making the HTTP call (e.g. viaclickLink(), executeAjaxEvent()orstartPage()`)。

    所以您可以在进行 http 调用之前使用 tester.getHttpSession().setAttribute(..., ...)

    【讨论】:

      【解决方案2】:

      使用 'tester.getHttpSession().setAttribute(..., ...)' 的建议有帮助吗?当我使用以下代码尝试时,我得到了原始错误中提到的 NullPointerException。

        public class RTApplication extends WebApplication
      {
          /**
           * @see org.apache.wicket.Application#getHomePage()
           */
          @Override
          public Class<? extends WebPage> getHomePage()
          {
                  return UserPage.class;
          }
      
          /**
           * @see org.apache.wicket.Application#init()
           */
          @Override
          public void init()
          {
              super.init();
      
              // needed for the styling used by the quickstart
              getCspSettings().blocking()
                  .add(CSPDirective.STYLE_SRC, CSPDirectiveSrcValue.SELF)
                  .add(CSPDirective.STYLE_SRC, "https://fonts.googleapis.com/css")
                  .add(CSPDirective.FONT_SRC, "https://fonts.gstatic.com");
      
              // add your configuration here
          }
      }
      
      public class UserPage extends WebPage {
          String userName;
          public UserPage() {
              super();
          }
          
          @Override
          protected void onInitialize() 
          {
              super.onInitialize();
              Session session = getSession();
              userName = session.getAttribute("userName").toString();
              System.out.println("UserPage: user is " + userName);
              add(new TextField<>("txtUserName", Model.of(userName)));
          } 
      }
      public class TestHomePage
      {
          private WicketTester tester;
      
          @BeforeEach
          public void setUp()
          {
              tester = new WicketTester(new RTApplication());
          }
          @Test
          public void userPageRendersSuccessfully()
          {
              System.out.println("Testing userPageRendersSuccessfully ");
              tester.getHttpSession().setAttribute("userName", "User set via tests");
              tester.getRequest().setAttribute("userName", "User set via tests");
              //start and render the test page
              System.out.println("Uesr name in session:" + tester.getHttpSession().getAttribute("userName"));
              tester.startPage(UserPage.class);
              //assert rendered page class
              tester.assertRenderedPage(UserPage.class);
              tester.assertModelValue("txtUserName", "User set via tests");
              System.out.println("Complete testing userPageRendersSuccessfully ");
          }
      }
      

      【讨论】:

      猜你喜欢
      • 2013-03-30
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多