我一直在使用CDIUnit和其他各种形式的CDI/SE解决方案来实现测试(junit),这些测试可以减少模拟,并更多地使用我的应用程序堆栈(我想是集成测试)。
无论如何,我也非常喜欢Spock进行测试,我认为应该抓紧时间从CDI/SE空间和Spock中混合一些东西,以便能够制定能够访问大部分CDI内容的规范。
许多CDI的单元运行程序(CDIUnit、WeldjUnit、deltaspike、为SE做cdi或Weld的随机博客片段)都是JUnit运行程序,似乎与Spock不太匹配。经过多次修补,我已经提炼出一个非常简单的东西:用非常简单的@Inject焊接/se spock。但它不起作用。
似乎weld确实“启动”了,我的可注射体的后构造函数也启动了。但是,在Spock feature方法中,对可注入的引用为null。在进一步的测试中,我使用@InjectSetter而不是实例变量,setter似乎使用了非空引用,但在我的feature方法启动时;引用再次为空。我还把Weld和container@Shared弄得一团糟,并试图在setupSpec()生命周期方法中初始化;同样的结果。
是否可以通过Spock测试进行简单的CDI操作?
这里有一个史波克的样本,展示了我正在努力实现的目标:
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()
}
}
}
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 = me.somethingToTest.upShift("fred")
then:
"FRED" == s
}
}
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);
}
}
因此,我观察/推测,真正发生的事情是斯波克创建了我的规范(“this”)的一个实例,然后在使用weld/se的设置中,我使用select()创建了另一个实例。get()调用('me')。简单的打印显示“我”!='这“实际上是注入发生在通过select()创建的托管实例上。get()。我想大概是这样。
所以我想我真正想要的是注射发生在“这个”上。一些谷歌搜索,我偶然发现了这个: CDI注入到现有的对象中,这是类似的东西。我受到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()
}
}
}
这是可行的,我的规范更自然一些:
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
}
}
现在来看看这是否有什么好处。。。。
Update2有一个性能问题:由于setup()在每个特征方法之前运行,因此每个特征方法都会初始化Weld,并扫描类路径和所有。
我把它移动到静态-但在这种情况下没有关闭(我找不到一个地方为它关闭钩子之外,但可能它甚至不需要测试):
class CdiSpecification extends Specification {
private static Weld weld
private static WeldContainer container
private static BeanManager beanManager
static {
weld = new Weld()
container = weld.initialize()
beanManager = container.getBeanManager()
}
def setup() {
CreationalContext<? extends CdiSpecification> creationalContext = beanManager.createCreationalContext(null)
AnnotatedType<? extends CdiSpecification> annotatedType = beanManager.createAnnotatedType((Class<? extends CdiSpecification>) this.getClass())
InjectionTarget<? extends CdiSpecification> injectionTarget = beanManager.createInjectionTarget(annotatedType)
injectionTarget.inject(this, creationalContext);
}
// def cleanup() {
// if (weld) {
// weld.shutdown()
// }
// }
}
根据更新2;我有些东西在工作。
Spock规范如下所示: 是一个测试记录列表,对于该列表的每个成员,方法将按顺序运行。我想要的是,列表的前k个成员运行一个线程,下面的k个成员在第二个线程中运行,等等...理论上,使用Executors框架和类(因为Spock依赖于JUnit),这可以相对容易地完成。 然而,问题是如何将更小的注入到具有方法的类中,因为Spock不允许构造函数,而JUnitCore需要类名(具有测试/规范的类),而
使用Spock运行集成测试(例如)的最佳方式是什么?我想引导整个Spring Boot应用程序,并执行一些HTTP调用来测试整个功能。 我可以用JUnit(首先运行应用程序,然后执行测试): 但是有了Spock,应用程序就不会启动了:
我对测试有点陌生(吓人,嗯),所以如果这是无知的话,请原谅我。 根据对测试框架所做的更改,spock spring 0.7-groovy-2.0是否与新的spring 3.2版本兼容? 我已经查看了正在测试的Spring 3.2文档: 以及新闻下的斯波克文档: 但是,没有任何东西可以帮助我判断新的Spring3.2测试框架是否仍然允许以Spring3.2测试(Spring3.2文档第11.3.4节
我在Spring控制器中加载数据库驱动pec.groovymethod.but我不知道如何调用Groovy脚本中的方法。有人能给我建议吗? 带着导游http://docs.groovy-lang.org/latest/html/documentation/guide-integrating.html 我只想访问http://127.0.0.1:8080/spock/test/spock然后运行数据
集成测试是对已经进行单元测试的各个部分的一种整合测试。集成是昂贵的,并且它出现在测试中。你必须把这个考虑到你的预计和时间表里。 理想情况下,你应该这样组织一个项目,使得最后没有一个阶段是必须通过显式集成来进行的。这比在项目过程中,随着事情完成逐渐集成事情要好得多。如果这是不可避免的,请仔细评估。
压力测试很有趣,一开始好像压测的目的是找出系统在负载下能不能工作。现实中,系统在负载下确实能工作,但在负载足够重的某些情况下不能工作。我把这叫做碰壁或撞响[1]。可能会有例外,但大多数情况下会有这么一堵“墙”。压测的目的是为了指出墙在哪里,然后弄清楚怎么把墙移得更远些。 压测计划需要在工程的早期就规划好,因为它经常有助于弄清楚到底什么是被期望的。两秒的网页请求是一个悲伤的失败还是一个了不起的成功?