使用 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你可以使用AopUtilsjdoc)的方法。简单的方法是使用 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