使用 Spring Boot 和 Camel 的 Spock:与分离模拟的零交互
Spock with Spring Boot and Camel: Zero interactions with detached mock
我在使用 spring 启动测试我的 camel 上下文时遇到了一些问题。
我正在使用 spring boot 1.5.6、spock 1.1-groovy-2.4、camel 2.19.2 和 camel-spring-boot-starter 2.19.2。
我正在使用 spock 模拟,我在 @TestConfiguration
class 中使用 DetachedMockFactory
。我所有的 bean 都使用构造函数注入。我将模拟的 @Repository
注入其中一个处理器 @Component
,我还将其注入我的测试 class 以定义交互。
我的测试用 @SpringBootTest
注释,classes 列表包括所有 Processor
实现和所有 RouteBuilder
扩展。我的 TestConfiguration
class 也有一个“@Import”。我什至在我的测试中为这个存储库 bean 使用构造函数注入!
但似乎注入到测试中的模拟class不是正在使用的模拟。有谁知道可能出了什么问题?我曾尝试 @DirtiesContext
在每次测试前后重新加载上下文,但这没有帮助。
DetachedMocks 行为不正确的问题,例如,看起来是同一个实例,通常是由一些框架将它们包装在代理中引起的。例如,这可能是由 Spring 中的 @Transactional
注释引起的,它创建了一个代理来促进 jdbc-session 管理。另见问题 #758
对于spring你可以使用AopUtils
(jdoc)的方法。简单的方法是使用 AopUtils.isAopProxy
检查它是否被 spring 代理,然后解包它。
public static <T> T getTargetObject(Object proxy) throws Exception {
if (AopUtils.isAopProxy(proxy)) {
return (T) ((Advised) proxy).getTargetSource().getTarget();
} else {
return (T) proxy;
}
}
并在测试中
def "sample service test"() {
given:
def sampleRepositryMock = getTargetObject(sampleRepositry)
when:
sampleService.doSomething() // simply invoke sampleRepositry.doSomething() in it
then:
1 * sampleRepositryMock.doSomething()
0 * _
}
编辑:从 Spock 1.2 开始,有一个扩展可以自动打开注入的 bean @UnwrapAopProxy
。
@Inject
@UnwrapAopProxy
SampleRepositry sampleRepositryMock
如果有人遇到同样的问题。
Spock 添加了额外的 @UnwrapAopProxy
代替上面提到的 util 方法。您也可以删除 DetachedMockFactory
@SpringSpy
@UnwrapAopProxy
Service service
我在使用 spring 启动测试我的 camel 上下文时遇到了一些问题。
我正在使用 spring boot 1.5.6、spock 1.1-groovy-2.4、camel 2.19.2 和 camel-spring-boot-starter 2.19.2。
我正在使用 spock 模拟,我在 @TestConfiguration
class 中使用 DetachedMockFactory
。我所有的 bean 都使用构造函数注入。我将模拟的 @Repository
注入其中一个处理器 @Component
,我还将其注入我的测试 class 以定义交互。
我的测试用 @SpringBootTest
注释,classes 列表包括所有 Processor
实现和所有 RouteBuilder
扩展。我的 TestConfiguration
class 也有一个“@Import”。我什至在我的测试中为这个存储库 bean 使用构造函数注入!
但似乎注入到测试中的模拟class不是正在使用的模拟。有谁知道可能出了什么问题?我曾尝试 @DirtiesContext
在每次测试前后重新加载上下文,但这没有帮助。
DetachedMocks 行为不正确的问题,例如,看起来是同一个实例,通常是由一些框架将它们包装在代理中引起的。例如,这可能是由 Spring 中的 @Transactional
注释引起的,它创建了一个代理来促进 jdbc-session 管理。另见问题 #758
对于spring你可以使用AopUtils
(jdoc)的方法。简单的方法是使用 AopUtils.isAopProxy
检查它是否被 spring 代理,然后解包它。
public static <T> T getTargetObject(Object proxy) throws Exception {
if (AopUtils.isAopProxy(proxy)) {
return (T) ((Advised) proxy).getTargetSource().getTarget();
} else {
return (T) proxy;
}
}
并在测试中
def "sample service test"() {
given:
def sampleRepositryMock = getTargetObject(sampleRepositry)
when:
sampleService.doSomething() // simply invoke sampleRepositry.doSomething() in it
then:
1 * sampleRepositryMock.doSomething()
0 * _
}
编辑:从 Spock 1.2 开始,有一个扩展可以自动打开注入的 bean @UnwrapAopProxy
。
@Inject
@UnwrapAopProxy
SampleRepositry sampleRepositryMock
如果有人遇到同样的问题。
Spock 添加了额外的 @UnwrapAopProxy
代替上面提到的 util 方法。您也可以删除 DetachedMockFactory
@SpringSpy
@UnwrapAopProxy
Service service