Mocking/autowiring 豆与 Spring 3.1.x 和 MockMvc

Mocking/autowiring beans with Spring 3.1.x and MockMvc

我正在使用 Spring 3.1.4,并尝试围绕我们使用 MockMvc 的身份验证编写一些集成测试。

我 运行 遇到的一个根本问题是因为我没有使用 Spring 3.2,所以我不能 @Autowire 一个 WebApplicationContext 对象在我的测试中,因此不能使用 MockMvcBuilders.webApplicationContextSetup(),所以我使用 xmlConfigSetup 代替。

我似乎遇到了一条有多个分支的路径,但都没有解决我所有的问题。

我的配置是这样的:

@ContextConfiguration(locations = {
        "classpath:/test-applicationContext.security.xml",
        "classpath:/test-mvc-dispatcher-servlet.xml"
})
@RunWith(SpringJUnit4ClassRunner.class)
public class SecurityTests extends AbstractJUnit4SpringContextTests {

    public static final String[] CONTEXT_CONFIG = {
            "classpath:/test-applicationContext.security.xml", "classpath:/test-mvc-dispatcher-servlet.xml"
    };

    @Autowired
    private Filter springSecurityFilterChain;

    @Before
    public void setUp() {
        ContextMockMvcBuilder xmlConfigSetup = MockMvcBuilders.xmlConfigSetup(CONTEXT_CONFIG);
        this.mockMvc = xmlConfigSetup.addFilters(springSecurityFilterChain).build();
    }

这里的优点就是我的springSecurityFilterChain@Autowired,方便提供给addFilters()缺点 是任何其他自动装配的 bean 与我的 MockMvc 配置中的实例 不同的实例 ,因为我实际上是在构建我的 servlet 上下文两次。这意味着如果我自动装配 UserDetailsService 并在我的集成测试中调整它(添加用户 "bob"),MockMvc 实例没有它。

选项 1: 使用上面的配置,我可以访问 MockMvc 实例中的任何 beans 吗?我还没有找到一种方法,这使得 "prepping" 无法进行任何集成测试。

选项 2: 删除 @ContextConfiguration 并让 MockMvc 驱动测试。这看起来更干净,但我不知道如何 create/inject 一个 Spring 安全过滤器链 - 因为它不再自动装配。 (None 我的 bean 是 - 这使得访问其他关键 bean,如 UserDetailsService 也有问题。)

选项 3: 我可以手动装配一个 WebApplicationContext 来包装 AbstractJUnit4SpringContextTests 超类中的 applicationContext,并提供 thisMockMvcBuilders.webApplicationContextSetup() 方法?这具有不需要两个单独的 servlet 上下文的优点,但是当我真的没有时手动构建它似乎特别 hacky - 而且我不确定如何将 Spring 安全过滤器链集成到这也行。

我正在寻求有关上述选项中哪些(如果有)最可行以及如何实现的建议。

不幸的是,升级到 Spring 的较新版本不是一个选项。

This post from the Spring team proposes a way to inject the WebApplicationContext into JUnit tests. They use a custom context loader specifically implemented for running integration tests, in addition to specifying the configuration location. The trouble is that their context loader depends on a class that is no longer available in any of the Spring repositories. However, it can be derived from some of the Spring MVC Test Samples.

Step 1: Create a custom context loader

class TestWebContextLoader extends AbstractContextLoader { ... }

此上下文加载器将用于加载您的 Spring 配置文件。

Step 2: Use the custom loader to load the Spring configuration files.

改变

@ContextConfiguration(locations = {
    "classpath:/test-applicationContext.security.xml",
    "classpath:/test-mvc-dispatcher-servlet.xml" })

@ContextConfiguration(loader = TestWebContextLoader.class,
    locations = {
    "classpath:/test-applicationContext.security.xml",
    "classpath:/test-mvc-dispatcher-servlet.xml" })

Step 3: Inject WebApplicationContext into your JUnit tests

public class SecurityTests extends AbstractJUnit4SpringContextTests {
  @Autowired
  private WebApplicationContext webApplicationContext;
}

Step 4: Build a mock using the injected WebApplicationContext

public class SecurityTests extends AbstractJUnit4SpringContextTests {
  @Autowired
  private WebApplicationContext webApplicationContext;

  @Before
  public void setUp() {
    MockMvc mock = MockMvcBuilders.webApplicationContextSetup(webApplicationContext).build();
  }
}

我创建了 a sample application 来演示概念以及上下文成功加载的位置。