具有自定义应用程序上下文的Spring集成测试 [英] Spring integration test with custom application context

查看:70
本文介绍了具有自定义应用程序上下文的Spring集成测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的应用程序,我创建了自己的ApplicationContext类型,该类型允许我以可能的应用程序所需的特定方式进行交互.由于该应用程序是桌面应用程序,因此我将创建如下上下文:

@SpringBootApplication
@Import(StandaloneConfiguration.class)
@PropertySource(value = {"application.properties", "server.properties"})
public class OpenPatricianApplication extends Application {
    private ApplicationContext context;
    @Override
    public void init() {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(OpenPatricianApplication.class);
        context = builder.contextClass(DependentAnnotationConfigApplicationContext.class).run(getParameters().getRaw().toArray(new String[0]));
        // more initialisation

        }
    }
}

现在,我想创建一个实际上依赖于我自己的ApplicationConext实现功能的Spring Boot集成测试.

@SpringBootTest(classes = {ServerTestConfiguration.class})
public class ServerIntegrationTest {
    private DependentAnnotationConfigApplicationContext context;
}

如何在测试中初始化我的context?必须创建context才能启动spring应用程序,此功能才能起作用,但是使用SpringBootTest批注时,在输入构造函数时,这种情况已经发生. 是否可以为现有的注释或参数添加其他注释或参数?应该完全不使用SpringBootTest注释这些性质的测试,而是手动创建应用程序吗?

解决方案

我找到的解决此问题的方法是完全放弃SpringBootTest批注,并将上下文构造为构造函数的一部分.另外,您也可以在BeforeAllBeforeEach方法中执行此操作,但是随着我的测试类扩展需要注入一些Bean的基类,构造函数似乎是正确的选择.

但是,不可行的是通过构造函数注入的方式在超类中注入Bean,因为对超级构造函数的调用必须是构造函数中的第一个调用,这将需要为它提供一个静态初始化程序块.上下文,我想尽可能避免使用静态内容,尤其是如果在测试结束时未正确清理上下文,则该上下文将作为已加载类的一部分存在于内存中,并可能消耗大量内存. >

下面是代码:

public class ServerIntegrationTest extends SaveLoadBase<CityWall> {

    public CityWallSerializationTest() {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(ServerTestConfiguration.class);
        DependentAnnotationConfigApplicationContext context = (DependentAnnotationConfigApplicationContext) builder.contextClass(DependentAnnotationConfigApplicationContext.class).run();
        setContext(context);
        setClientServerEventBus((AsyncEventBus) context.getBean("clientServerEventBus"));
        setLoadAndSaveService(context.getBean(TestableLoadAndSaveService.class));
    }
}

For my application I created my own type of ApplicationContext that allows me to interact in specific manners that are needed for may application. As the application is a desktop application, I create the context like this:

@SpringBootApplication
@Import(StandaloneConfiguration.class)
@PropertySource(value = {"application.properties", "server.properties"})
public class OpenPatricianApplication extends Application {
    private ApplicationContext context;
    @Override
    public void init() {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(OpenPatricianApplication.class);
        context = builder.contextClass(DependentAnnotationConfigApplicationContext.class).run(getParameters().getRaw().toArray(new String[0]));
        // more initialisation

        }
    }
}

Now I want to create a Spring Boot integration test that actually relies on the functionality of my own ApplicationConext implementation.

@SpringBootTest(classes = {ServerTestConfiguration.class})
public class ServerIntegrationTest {
    private DependentAnnotationConfigApplicationContext context;
}

How do I go about initializing my context in the test? The context must be created in order to start the spring application for this to work, but with the SpringBootTest annotation this already happened, when the constructor is entered. Are there any additional annotations or parameter for existing ones that can be applied? Should tests of these nature not be annotated with SpringBootTest at all and the application created manually?

解决方案

The approach that I found to solve this issue is to forgo the SpringBootTest annotation altogether and construct the context as part of the constructor. Alternatively you could also do it in the BeforeAll or BeforeEach method, but as my test class extends a base class that needs some beans injected, the constructor seemed the right choice.

However what does not work is injecting the beans in the super class by way of constructor injection, as the call to the super constructor has to be the first call in the constructor and that would necessitate to have a static initializer block for the context and I want to avoid static stuff as much as possible, especially if the context is not properly cleaned up at the end of the test, it would live on as part of the loaded class in memory and potentially consume lot of memory.

So here is the code:

public class ServerIntegrationTest extends SaveLoadBase<CityWall> {

    public CityWallSerializationTest() {
        SpringApplicationBuilder builder = new SpringApplicationBuilder(ServerTestConfiguration.class);
        DependentAnnotationConfigApplicationContext context = (DependentAnnotationConfigApplicationContext) builder.contextClass(DependentAnnotationConfigApplicationContext.class).run();
        setContext(context);
        setClientServerEventBus((AsyncEventBus) context.getBean("clientServerEventBus"));
        setLoadAndSaveService(context.getBean(TestableLoadAndSaveService.class));
    }
}

这篇关于具有自定义应用程序上下文的Spring集成测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆