测试阶段的@Inject字段

时间:2016-07-02 15:00:21

标签: java maven log4j cdi

我正在为我的应用添加日志记录功能,而我正在使用slf4j实现的log4j。为了简化我的代码,我有一个帮助程序类来生成一个记录器(这个想法不是我的,我是从Beginning Java EE 7 by Antonio Goncalves获取的),类是这样的:

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggerProducer {

    @Produces
    public Logger createLogger(InjectionPoint injPoint) {
        return LoggerFactory.getLogger(injPoint.getMember().getDeclaringClass());
    }
}

所以在我的课上我所要做的(理论上)是:

public class SomeClass {
    @Inject private Logger logger; // this could be private or default, doesn't matter
}

问题是在测试阶段我没有启用CDI,因为我在容器外运行代码。我无法手动注入,因为我有一些带有自己的记录器的抽象类,所以我无法实例化该类并为其分配Logger实例。

有没有办法在测试阶段“启用”CDI?我的项目是用Maven构建的,我将部署到Wildfly 10 Server。提前感谢您的回答。

注意

我不能做像

这样的事情
public class SomeClassTest {
    private SomeClass someClass; // this is the class I want to test

    @Before
    public void init() {
        someClass.logger = LoggerFactory.getLogger(SomeClass.class);
    }

    @Test
    public void someTest(){...}
}

因为我有一些带有自己的私有Logger logger属性的抽象类,我需要保持这种方式(我不能声明它protected)因为我想要跟踪一下消息被抛出,所以我需要保持记录器私有。例如。我有类似

的东西
public abstract class MyAbstract {
    @Inject
    private Logger logger;
}

public class MyConcrete extends MyAbstract {
    @Inject
    private Logger logger;
}

我可以从测试类中将MyConcrete.logger设置为默认值,但我可以t do that for MyAbstract.logger because they are in different packages and I can't instantiate MyAbstract`,我能正确解释吗?

注2

我的项目结构是这样的:

package common

import org.slf4j.logger
...

public abstract class Generic {
    @Inject
    private Logger logger;

    public void doSomethingGeneric(){
        // do something and log it
    }
}

package specific

import ...

public class Concrete extends Generic{
    @Inject
    Logger logger;

    // some concrete methods...
}

package specific

public class ConcreteTest {
    private Concrete concrete;

    @Before
    public void init() {
        concrete = new Concrete();
        concrete.logger = LoggerFactory.getLogger(Concrete.class); // Dependency injection by hand
    }

    // some @Test methods
}

最终,来自@Test的{​​{1}}方法调用ConcreteTest,因为它继承到Concrete.doSomethingGeneric()实例。问题是concrete使用doSomethingGeneric()记录器进行日志记录,我不知道如何以干净的方式满足该依赖项(我不希望使用生产所不需要的setter方法来破解我的代码)

1 个答案:

答案 0 :(得分:1)

您可以使用模拟测试单元执行此操作:

["Marseille", "Marsan", "Martin"].map { |x| x[0,4] }
# => ["Mars", "Mars", "Mart"]

此处,mockito运行时和代理将管理注入,您甚至可以对记录器本身进行验证。