java - 在 ServletContextListener 使用 web.xml 中的文件路径之前设置 JUnit 测试的系统属性

标签 java spring junit servletcontextlistener spring-profiles

我正在修改使用 Spring 3.1.4 的旧项目。

我正在尝试使用 StartupListener 来配置 Logback:

public class LoggingStartupListener implements ServletContextListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingStartupListener.class.getName());


@Override
public void contextInitialized(final ServletContextEvent sce) {
    final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
    context.reset();
    final JoranConfigurator configurator = new JoranConfigurator();
    final ServletContext servletContext = sce.getServletContext();
    final StringBuilder filePath = new StringBuilder(100);
    filePath.append(servletContext.getRealPath("/"));
    filePath.append(servletContext.getInitParameter("logFileName"));
    InputStream configStream = null;
    try {
        configStream = FileUtils.openInputStream(new File(filePath.toString()));

...

它正在从 web.xml 读取文件路径:

<context-param>
    <param-name>logFileName</param-name>
    <param-value>/WEB-INF/config/${spring.profiles.active}/logback.xml</param-value>
</context-param>

现在,当我运行 JUnit 测试时,我总是遇到异常:

java.io.FileNotFoundException: File '/var/folders/v7/1r3m8y8j487dqj7vmvb4n4kxcw70fj/T/tomcat-embedded-77438108580291256392.tmp/webapps/myproject/WEB-INF/config/${spring.profiles.active}/logback.xml' does not exist
at org.apache.commons.io.FileUtils.openInputStream(FileUtils.java:136)

这意味着 spring.profiles.active 属性永远不会被解析。

我尝试了各种方法:

1)我尝试在测试前设置属性:

@BeforeClass
public static void setSystemProperty() {
    System.out.println("---------------------BeforeClass--------------------");
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.getEnvironment().setActiveProfiles("local");
    ctx.refresh();

    System.setProperty("spring.profiles.active", "local");
}

但是它不起作用,因为这个方法是在错误抛出后调用的。 (“----------BeforeClass--------------”出现在日志中错误之后很久。)

2)我尝试在测试类之前使用注释:

@ActiveProfiles(profiles = "local")

3)我尝试使用 spring-test.properties 文件设置属性:

spring.profile.active=local

并将其包含在测试上下文中:

<context:property-placeholder location="classpath:spring-test.properties"/>

-> 没有任何效果

4)我什至尝试直接在 ServletContextListener 中设置属性:

@Override
public void contextInitialized(final ServletContextEvent sce) {
    System.setProperty("spring.profiles.active", "local");
    ...

这真的让我感到惊讶,因为这应该有效,不是吗?

我遇到这些问题是因为我使用的是旧的 Spring 版本吗?我在其他具有更高 Spring 版本的项目中从未遇到过这些问题。 或者我错过了什么?

我可以将监听器配置为稍后启动吗?或者我可以配置单元测试以在 ServletContextListener 启动之前设置系统属性吗?

或者以不同的方式初始化 logback 以避免这些问题会更好 - 但为什么它们不会出现在其他项目中?

我发现了这个,但我不知道这是否适用于我的情况: Spring-test and ServletContextListener in web.xml

它表示无法使用 Spring MVC Test 配置 ServletContextListener。它说我可以尝试用

覆盖上下文参数
wac.getServletContext().setInitParameter(name, value);

但我不知道何时何地执行此操作,因为显然在初始化测试类之前已读取了 web.xml。

提前非常感谢您的任何提示

最佳答案

我使用了 logback spring 扩展而不是我们自己的实现,问题就消失了!

我使用了这个文档: https://github.com/qos-ch/logback-extensions/wiki/Spring

其特点之一是: - “使用 Spring 资源路径和系统属性占位符指定 logback.xml 位置。”

正是我所需要的。我使用的是 logback-ext-spring 版本 0.1.4。

关于java - 在 ServletContextListener 使用 web.xml 中的文件路径之前设置 JUnit 测试的系统属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39857234/

相关文章:

java - 单元测试Java中单例类的线程安全性?

java - 在两个不同的端口上运行 Tomcat 服务器

java - 如何通过比较值对 HashMap 的条目进行排序,其中每个值都是一个 int[]?

model-view-controller - javax.validation.ConstraintViolationException : Bean Validation constraint(s) violated on preUpdate validation

java - 为 Spring Security 设置 LDAP 查询超时

java - 如何在 SQLite 上正确运行 JUnit 测试

java.util.ArrayList 无法转换为 java.lang.Long hibernate 分离条件

java - Maven 发布 : Local Modifications to . java 文件

java - JSP 无法正确评估数组索引

java - 如何模拟下游方法调用?