首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Spring测试中定义的另一个spock Mock没有被注入

在Spring测试中定义的另一个spock Mock没有被注入
EN

Stack Overflow用户
提问于 2021-05-27 06:38:35
回答 1查看 861关注 0票数 1

我在Spock中编写了一个Spring,其中注入的依赖项需要在bean的构造函数中执行一些操作。

我已经在我的规范中创建了一个模拟并用@SpringBean对其进行了注释,并为模拟定义了一些行为,然后我期望它被注入到依赖于模拟类的bean中。一些被模拟的实例被注入到bean中,但是我无法定义行为,这是我所期望的。

我可以从(https://spockframework.org/spock/docs/1.3/module_spring.html)看到:

Spock的@SpringBean实际上在ApplicationContext中创建了一个代理,该代理将所有内容转发给当前的模拟实例。代理的类型由带注释的字段的类型决定。代理在安装阶段将自己附加到当前的模拟,这就是为什么必须在初始化字段时创建模拟。

这个实例似乎不一样,我猜文档中的引号是这样说的,但我希望能够定义行为,并在bean中有它,但是方法只返回默认值,这意味着模拟注入没有重新定义它的行为。

从我实现的另一个扩展测试中可以看出,它的工作方式与我预期的一样,即可以在规范中定义行为并按预期注入,但为了示例的目的,我隔离了问题。

解决办法是显式创建类并注入依赖项,但在发生此问题的测试中,依赖项必须注入依赖关系层次结构中非常深的依赖项中。

有人能确定我错过了什么吗?

试验结果如下:

代码语言:javascript
运行
复制
package com.test.springmockspock

import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification

@SpringBootTest
class SpringspockmockApplicationSpec extends Specification {

    @Autowired
    SpringspockmockApplication sut

    @SpringBean
    Factory factory = Mock() {
        getInt() >> 99
    }

    @Autowired
    Factory autowiredFactory

    void 'hello'() {
        when:
        def insideSUTFactory = sut.factory

        then:

        factory.getInt() == 99
//        sut.intFromFactory == 42              // this should have been 99
        autowiredFactory == insideSUTFactory    // true
        factory == insideSUTFactory             // false (but should have been true)

    }
}

工厂的课程是:

代码语言:javascript
运行
复制
package com.test.springmockspock;

import org.springframework.stereotype.Component;

@Component
public class Factory {
    public Producer get() {
        return new Producer();
    }

    public int getInt() {
        return 45;
    }
}
代码语言:javascript
运行
复制
package com.test.springmockspock;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;


@ComponentScan("com.test.springmockspock")
@SpringBootApplication
public class SpringspockmockApplication implements CommandLineRunner {

    private final Factory factory;
    private final Producer producer;

    public SpringspockmockApplication(Factory factory) {
        this.factory = factory;
        this.producer = factory.get();
        return;
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringspockmockApplication.class, args);
    }

    public Factory getFactory() {
        return factory;
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Hello world");
    }

    public int getIntFromFactory() {
        return factory.getInt();
    }
}

The build.gradle.kts

代码语言:javascript
运行
复制
plugins {
    groovy
    application

    id("org.springframework.boot") version "2.5.0"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"

}

repositories {
    mavenCentral()
}

dependencies {
    // Use the latest Groovy version for Spock testing
    testImplementation("org.codehaus.groovy:groovy:3.0.7")

    // Use the awesome Spock testing and specification framework even with Java
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.spockframework:spock-spring:2.0-M4-groovy-3.0")
    testImplementation("org.spockframework:spock-core:2.0-M4-groovy-3.0")
    testImplementation("junit:junit:4.13.1")
    testRuntimeOnly("net.bytebuddy:byte-buddy:1.11.0") // allows mocking of classes (in addition to interfaces)
    testRuntimeOnly("org.objenesis:objenesis:3.2")      // allows mocking of classes without default constructor (together with ByteBuddy or CGLIB)

    // This dependency is used by the application.
    implementation("com.google.guava:guava:30.0-jre")
    implementation("org.springframework.boot:spring-boot-starter")
}

application {
    mainClass.set("com.test.springmockspock.App")
}
EN

回答 1

Stack Overflow用户

发布于 2021-05-28 17:20:33

你已经引用了确切的问题。@SpringBean将创建一个代理,该代理稍后会附加到规范中,就像在Spock世界中一样,交互是由规范管理的,而不是单个的模拟。

现在,spring上下文将在将模拟附加到规范之前初始化,因此您只获得代理实例而不进行任何交互。然后将这个代理注入构造函数,在构造函数中它将响应它的默认行为(返回null或0)。初始化上下文之后,模拟将被附加到规范中,现在可以处理交互。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67716891

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档