【发布时间】:2016-07-02 15:00:21
【问题描述】:
我正在向我的应用程序添加日志记录功能,并且我正在使用由log4j 实现的slf4j。为了简化我的代码,我有一个辅助类来生成一个记录器(这个想法不是我的,我是从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 服务器。提前感谢您的回答。
注意
我不能这样做
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 forMyAbstract.loggerbecause they are in different packages and I can't instantiateMyAbstract`,我解释正确吗?
注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
}
最终,来自ConcreteTest 的@Test 方法调用Concrete.doSomethingGeneric(),因为它被继承到concrete 实例。问题是doSomethingGeneric() 使用Generic 记录器进行日志记录,我不知道如何以干净的方式满足这种依赖关系(我不希望使用生产中不必要的setter 方法来破解我的代码)
【问题讨论】:
-
有arquillian.org、DeltaSpike Test Control 和jglue.org/cdi-unit 几种方法来做到这一点。
-
“在测试阶段”:你的意思是通过 JUnit 运行单元测试吗?
-
@Heri,没错。我的意思是在
src/test/java中运行我所有的@Test方法时 -
@JohnAment, AFAIK, Arquillian 用于集成测试(在容器内测试);其他两个工件用于编写基于 CDI 的测试。我的情况也不是。我只想在测试阶段获得
Logger的实例 -
如果你使用 spring 注释 @RunWith(SpringJUnit4ClassRunner.class) 会有所帮助,可能后面跟着注释 @ContextConfiguration(classes={ MyConfigClass1.class, MyConfigClass2.class })。我不知道是否有没有弹簧的替代品。