junit spring-@BeforeClass在@ContextConfiguration之前运行

时间:2018-10-11 06:36:16

标签: java spring junit spring-security

我想在junit测试中使用spring security手动进行登录,所以我使用@WebAppConfiguration@BeforeClass setUp()方法来设置springcontext以便使用springsecurity代码。
但是,由于@BeforeClass在junit类注释@WebAppConfiguration@ContextConfiguration之前运行,因此@Autowired的{​​{1}}在private WebApplicationContext wac中为空,并导致错误消息如下。
然后我将setUp()更改为@BeforeClass,然后问题解决了。
有什么方法仍然可以使用@Before并且可以解决问题吗?

测试类

@BeforeClass

错误消息

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;


@ContextConfiguration(locations = {
    "classpath:/springTest/applicationContext_test.xml",
    "classpath:/applicationContext-security.xml",
    "classpath:/spring/applicationContext-repository.xml"
    })
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class xxxTest {

  @Autowired
  private xxx target;

  @Autowired
  private LoginAuthenticationProvider loginAuthenticationProvider;

  @Autowired
  private WebApplicationContext wac;

  //set the context
  @BeforeClass
  public void setUp() throws ServletException {
    ServletContextListener listener = new ContextLoaderListener(wac);
    ServletContextEvent event = new ServletContextEvent(new MockServletContext(""));
    listener.contextInitialized(event);
  }

  //mock login(manually login)
  @Test
  public void test01() {
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
    Authentication authentication = loginAuthenticationProvider.authenticate(token);
    SecurityContextHolder.getContext().setAuthentication(authentication);

    //other test code......
  }


}

1 个答案:

答案 0 :(得分:4)

@BeforeClass是一个静态方法,这就是@Autowired变量提供null的原因。 1)可以使用的一种方法是使用自定义布尔标志:

private static boolean isInitialized = false;
.....
public void setUp() {
    if (isInitialized) {
        return;
    }
    // do the setup
    isInitialized = true;
}

2)另一种方法(我没有尝试过,但理论上应该可行)是使用@BeforeAll注释。