当前位置: 首页 > 知识库问答 >
问题:

为什么@SpringBootTest在构造函数注入中需要@Autow的

古棋
2023-03-14

一个更一般的问题。如果在常规Spring托管类中使用构造函数注入,则这些类将自动连接,而不需要@autowired注释,即:

@Service
class MailService(
  private val projectService: ProjectService,
  private val mailer: Mailer
) { ... }

在@SpringBootTest类中遵循相同的构造函数注入原则,您需要将@Autowired注释设置为构造函数参数,否则它将无法注入该类,即:

@SpringBootTest
internal class MailerTest(
  @Autowired private val mailer: Mailer
) { ... }

为什么会出现这种差异?

共有1个答案

林元明
2023-03-14

在SpringBoot应用程序的情况下,负责连接beans的是spring。

在JUnit 5的情况下,Spring管理的Beans必须注入到JUnit管理的测试类实例中。幸运的是,JUnit 5提供了一种通过ParameterResolver来做到这一点的方法。

< code>@SpringBootTest注册SpringExtension,除了其他功能之外,它还可以作为一个参数解析器:

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
    Parameter parameter = parameterContext.getParameter();
    Executable executable = parameter.getDeclaringExecutable();
    Class<?> testClass = extensionContext.getRequiredTestClass();
    PropertyProvider junitPropertyProvider = propertyName ->
    extensionContext.getConfigurationParameter(propertyName).orElse(null);
    return (TestConstructorUtils.isAutowirableConstructor(executable, testClass, junitPropertyProvider) ||
            ApplicationContext.class.isAssignableFrom(parameter.getType()) ||
            supportsApplicationEvents(parameterContext) ||
            ParameterResolutionDelegate.isAutowirable(parameter, parameterContext.getIndex()));
}

ParameterResolutionDelegate.isAutowirable依赖于注释来确定是否可以从Spring的Application Context中注入参数

public static boolean isAutowirable(Parameter parameter, int parameterIndex) {
    Assert.notNull(parameter, "Parameter must not be null");
    AnnotatedElement annotatedParameter = getEffectiveAnnotatedParameter(parameter, parameterIndex);
    return (AnnotatedElementUtils.hasAnnotation(annotatedParameter, Autowired.class) ||
            AnnotatedElementUtils.hasAnnotation(annotatedParameter, Qualifier.class) ||
            AnnotatedElementUtils.hasAnnotation(annotatedParameter, Value.class));
}

事实上,如果省略@Autowired注释,JUnit会抱怨缺少ParameterResolver:

org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [test.Mailer mailer] in constructor [public test.MailServiceTest(test.Mailer)].
 类似资料:
  • 问题内容: 我对此代码有疑问:https : //github.com/reactjs/redux/blob/master/examples/async/containers/App.js 特别: 我猜这是一个两部分的问题。 为什么我需要将句柄更改设置为类的实例,我不能只对handleChange使用静态函数并直接在类中调用它 ? 我不知道这是怎么回事: 谢谢 问题答案: 以相反的顺序回答… 返回

  • 我试图将构造函数注入模式应用于CDI应用程序中的bean,但遇到以下错误消息: 的确,为了使用构造函数注入模式,我有意地设计了一个需要参数的构造函数的类: 通过查看不可代理bean类型的CDI规范,我看到: 3.15.不可修复的bean类型 容器使用代理提供某些功能。容器不能代理某些合法bean类型: 没有不带参数的非私有构造函数的类, 被宣布为最终的类, 具有非静态的、具有公共可见性、受保护可见

  • 问题内容: 必须使用无参数构造函数(像Hibernate这样的工具会在此构造函数上使用反射来实例化对象)。 我得到了这个手挥手的答案,但是有人可以进一步解释吗?谢谢 问题答案: hibernate,并且通常通过反射创建对象的代码用于创建类的新实例。此方法需要一个公共的无参数构造函数才能实例化该对象。对于大多数用例,提供无参数构造函数不是问题。 有一些基于序列化的技巧可以解决没有no-arg构造函数

  • 我问这个问题是因为在Python和Java中,如果父类构造函数需要0参数,则不需要调用super()。 Javascript 蟒蛇 Java

  • 问题内容: 在Pro Spring 3丛书的第4章-Spring中的IOC和DI简介-第59页中的“ Setter注入与构造方法注入”部分中,一段说 包括Spring,提供了一种机制来确保在使用Setter Injection时定义了所有依赖关系,但是通过使用Constructor Injection,你可以以与容器无关的方式声明对依赖关系的要求。” 你能举例说明一下吗 问题答案: 将必需的依赖项

  • 问题内容: 使用Promises时,为什么不能在代码库的其他地方触发并定义? 我不明白为什么,应该在声明诺言的地方本地化逻辑。这是疏忽大意,还是强制执行此参数有好处吗? 我相信执行程序功能应该是可选的,并且它的存在应该确定promise是否封装了解决方案。没有这样的授权,promise的可扩展性就更大,因为您不必立即启动异步。承诺也应该是可重置的。这是1档开关,1或0 或。可以附加许多平行和顺序的