Java 如何从Spock测试进行CDI/SE?
我一直在使用CDIUnit和其他各种形式的CDI/SE解决方案来实现测试(junit),这些测试可以减少模拟,并更多地使用我的应用程序堆栈(我想是集成测试) 无论如何,我也非常喜欢Spock进行测试,我认为应该抓紧时间从CDI/SE空间和Spock中混合一些东西,以便能够制定能够访问大部分CDI内容的规范 许多用于CDI的单元运行程序(CDIUnit、weldjunit、deltaspike、用于CDI或weld for SE的随机博客片段)都是JUnit运行程序,对于Spock来说似乎并不太适合。经过多次修补,我提炼出了一个非常简单的东西:weld/se+spock和真正简单的@Inject。但它不起作用 似乎weld确实“启动”了,我的可注射体的后构造函数也启动了。但是,在Spock feature方法中,对可注入的引用为null。在进一步的测试中,我使用@InjectSetter而不是实例变量,setter似乎使用了非空引用,但在我的feature方法启动时;引用再次为空。我还把Weld和container@Shared弄得一团糟,并试图在setupSpec()生命周期方法中初始化;同样的结果 是否可以通过Spock测试进行简单的CDI操作? 下面是一个Spock的样本,展示了我试图实现的目标:Java 如何从Spock测试进行CDI/SE?,java,groovy,junit,cdi,spock,Java,Groovy,Junit,Cdi,Spock,我一直在使用CDIUnit和其他各种形式的CDI/SE解决方案来实现测试(junit),这些测试可以减少模拟,并更多地使用我的应用程序堆栈(我想是集成测试) 无论如何,我也非常喜欢Spock进行测试,我认为应该抓紧时间从CDI/SE空间和Spock中混合一些东西,以便能够制定能够访问大部分CDI内容的规范 许多用于CDI的单元运行程序(CDIUnit、weldjunit、deltaspike、用于CDI或weld for SE的随机博客片段)都是JUnit运行程序,对于Spock来说似乎并不太适
package fhw
import spock.lang.Specification
import javax.inject.Inject
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import spock.lang.Shared
public class Chompers
extends Specification
{
def Weld weld
def WeldContainer container
def setup()
{
println this
weld = new Weld()
container = weld.initialize()
container.instance().select(this.class).get()
//container.instance().select(this.class)
}
@Inject
def SomethingToTest somethingToTest;
//@Inject
//def setSomethingToTest(SomethingToTest sst)
//{
// somethingToTest = sst
// println "setter fired and somethingToTest is null? " + (null == somethingToTest)
//}
def "my first Test"()
{
given:
println "given I used weld wrapper spec From spock (instance " + this + ")"
when:
println "when I do something, in this case, like just haveing @Inject annotation"
then:
somethingToTest
}
}
更新
我有点“工作”。不确定原因或方式,甚至不确定它是否有任何好处(对于解决方案)。我想知道更多关于发生了什么以及为什么。样本:
package fhw
import org.junit.runner.RunWith
import spock.lang.*
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import javax.enterprise.inject.Instance
class WeldSpec
extends Specification
{
def Weld weld
def WeldContainer container
def me
def setup()
{
weld = new Weld()
container = weld.initialize()
me = container.instance().select(this.class).get()
}
def cleanup()
{
if(weld)
{
weld.shutdown()
}
}
}
更新2 因此,我观察/推测,真正发生的事情是斯波克创建了我的规范的一个实例(“this”),然后在使用weld/se的设置中,我使用select().get()调用(“me”)创建了另一个实例。简单的打印显示“我”!='这“实际上是通过select().get()创建的托管实例上发生的注入。我想大概是这样 所以我想我真正想要的是在“这个”上注射。通过谷歌搜索,我偶然发现:这是一个类似的东西。我受到DeltaSpike的injectFields和重构WeldSpec的启发,比如:
package fhw
import spock.lang.*
import javax.enterprise.inject.spi.BeanManager
import javax.enterprise.inject.spi.InjectionTarget
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import javax.enterprise.context.spi.CreationalContext
import javax.enterprise.inject.spi.AnnotatedType
class WeldSpec
extends Specification
{
def Weld weld
def WeldContainer container
def setup()
{
weld = new Weld()
container = weld.initialize()
BeanManager beanManager = container.getBeanManager()
CreationalContext<? extends WeldSpec> creationalContext = beanManager.createCreationalContext(null)
AnnotatedType<? extends WeldSpec> annotatedType = beanManager.createAnnotatedType((Class<? extends WeldSpec>) this.getClass())
InjectionTarget<? extends WeldSpec> injectionTarget = beanManager.createInjectionTarget(annotatedType)
injectionTarget.inject(this, creationalContext);
}
def cleanup()
{
if(weld)
{
weld.shutdown()
}
}
}
现在看看这是否有什么好处……根据更新2;我有些东西在工作 Update2有一个性能问题:由于setup()在每个特征方法之前运行,每个特征方法都会初始化Weld,并扫描类路径和所有 我将它移到了static,但在这种情况下没有关机(我在关机挂钩之外找不到一个地方放置它,但可能它甚至不需要用于测试):
类CDisspecification扩展了规范{
专用静态焊缝
专用静态焊接容器
专用静态BeanManager BeanManager
静止的{
焊缝=新焊缝()
容器=焊接。初始化()
beanManager=container.getBeanManager()
}
def设置(){
creationalcontext看看这个问题,它可能会有帮助:有趣——昨晚看到了那篇帖子,但没有仔细检查,因为这起案件涉及阿奎利安。海报的工作还可以,但不确定它是否会帮助我。它确实添加了另一个数据点;我不是唯一一个看到这一点的人。我已经探索过(目前正在探索)使用spock扩展并点击visitSpecAnnotation()等生命周期方法,看看CDI/Weld/SE在那里是否能更好地工作。也许我应该看看visitFeatureAnnotation()太好了。你使用的是什么版本的weld?主要问题是注入到你的spock案例中是不起作用的,但是如果你至少在2.x上,那么现在有一些选项可以选择“org.spockframework:spock core:1.0-groovy-2.4”和“org.jboss.weld.se:weld se-se core:2.2.10.Final”。我很想知道更多关于这些选项的信息;我真的很想得到这个to工作…Spock扩展(使用AbstractAnnotationDrivenExtension)几乎可以让我在同一个地点启动一个容器,但是斯波克在调用特征方法之前擦除了注射。谢谢你的反馈。我没有考虑在每个特征方法之前制作CDI容器的性能。但是,我觉得从每个特征方法开始使用一个新容器是很重要的。也许斯波克的setupSpec()和cleanupSpec()可以摆脱静态块,在fixture关闭时提供一个钩子?
package fhw;
import javax.annotation.PostConstruct;
import javax.inject.Named;
@Named
public class SomethingToTest
{
public SomethingToTest() {}
@PostConstruct
private void init()
{
System.out.println("SomethingToTest: post construction");
}
public String upShift(String in)
{
String s = null;
if(null != in)
{
s = in.toUpperCase();
}
return(s);
}
}
package fhw
import spock.lang.*
import javax.enterprise.inject.spi.BeanManager
import javax.enterprise.inject.spi.InjectionTarget
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import javax.enterprise.context.spi.CreationalContext
import javax.enterprise.inject.spi.AnnotatedType
class WeldSpec
extends Specification
{
def Weld weld
def WeldContainer container
def setup()
{
weld = new Weld()
container = weld.initialize()
BeanManager beanManager = container.getBeanManager()
CreationalContext<? extends WeldSpec> creationalContext = beanManager.createCreationalContext(null)
AnnotatedType<? extends WeldSpec> annotatedType = beanManager.createAnnotatedType((Class<? extends WeldSpec>) this.getClass())
InjectionTarget<? extends WeldSpec> injectionTarget = beanManager.createInjectionTarget(annotatedType)
injectionTarget.inject(this, creationalContext);
}
def cleanup()
{
if(weld)
{
weld.shutdown()
}
}
}
package fhw
import spock.lang.*
import javax.inject.Inject
import fhw.spock.*
public class Bonnie
extends WeldSpec
{
@Inject
def SomethingToTest somethingToTest;
def "my silly first cdi-spock test"()
{
when:
def s = somethingToTest.upShift("fred")
then:
"FRED" == s
}
}