[英]@SpringBootTest with MapStruct requires Impl
I have following test:我有以下测试:
@SpringBootTest(classes = {SomeService.class, DtoMapperImpl.class})
class SomeServiceTest {
And following mapper:和以下映射器:
@Mapper(componentModel = "spring")
public interface DtoMapper {
EntityDto toDto(Entity entity);
}
I'm not changing packages (this means DtoMapperImpl is in the same package as DtoMapper )我没有更改包(这意味着DtoMapperImpl与 DtoMapper 在同一个package中)
As soon as I change Impl to interface my test fails:一旦我将 Impl 更改为接口,我的测试就会失败:
@SpringBootTest(classes = {SomeService.class, DtoMapper.class})
class SomeServiceTest {
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'someService': Unsatisfied dependency expressed through constructor parameter 2; Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'someService': Unsatisfied dependency expressed through constructor parameter 2 ; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'DtoMapper' available: expected at least 1 bean which qualifies as autowire candidate.嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有可用的“DtoMapper”类型的合格 bean:预计至少有 1 个 bean 有资格作为自动装配候选者。 Dependency annotations: {}依赖注解:{}
Can you please advise best way solving this?你能建议解决这个问题的最佳方法吗? I'm on MapStruct 1.3.1.Final我在 MapStruct 1.3.1.Final
Create following configuration (should point where mappers are):创建以下配置(应该指向映射器所在的位置):
@TestConfiguration
@ComponentScan("some.package.mapper")
public class MappersConfig {
}
And modify slice:并修改切片:
@SpringBootTest(classes = {SomeService.class, MappersConfig.class})
class SomeServiceTest {
The problem actually has nothing to do with MapStruct, but rather to how SpringBootTest#classes
is used.问题实际上与 MapStruct 无关,而是与SpringBootTest#classes
的使用方式有关。
The classes
in SpringBootTest
is meant to provide your components that should be used to load in the test. SpringBootTest
的classes
旨在提供应该用于加载测试的组件。
From the JavaDoc:来自 JavaDoc:
The component classes to use for loading an
ApplicationContext
.用于加载ApplicationContext
的组件类。 Can also be specified using@ContextConfiguration(classes=...)
.也可以使用@ContextConfiguration(classes=...)
指定。 If no explicit classes are defined the test will look for nested@Configuration
classes, before falling back to a@SpringBootConfiguration
search.如果没有定义明确的类,测试将在回@SpringBootConfiguration
搜索之前查找嵌套的@Configuration
类。 Returns: the component classes used to load the application context返回: 用于加载应用程序上下文的组件类
In your case you have 2 classes:在您的情况下,您有 2 个课程:
SomeService
- which I assume is a class annotated with @Service
and Spring will correctly load it SomeService
- 我假设它是一个用@Service
注释的类,Spring 会正确加载它DtoMapper
- this is the MapStruct mapper which is an interface and it isn't a component. DtoMapper
- 这是 MapStruct 映射器,它是一个接口,而不是一个组件。 The component which you want for your tests is DtoMapperImpl
您需要用于测试的组件是DtoMapperImpl
You have several options to fix this:您有多种选择可以解决此问题:
You can use the DtoMapperImpl
(the Spring Component class) in your SpringBootTest#classes
, your test will then load the correct component您可以在SpringBootTest#classes
使用DtoMapperImpl
(Spring Component 类),然后您的测试将加载正确的组件
@TestConfiguration
@ComponentScan("com.example.mapper")
public class MappersConfig {
}
And then use this in your SpringBootTest#classes
.然后在您的SpringBootTest#classes
使用它。 Eg例如
@SpringBootTest(classes = {SomeService.class, MappersConfig.class})
class SomeServiceTest {
...
}
I would suggest a little improvement for accepted answer so that you don't have to write package name as hard-coded string, but use ComponentScan basePackageClasses instead:我建议对已接受的答案进行一些改进,这样您就不必将 package 名称写为硬编码字符串,而是改用 ComponentScan basePackageClasses:
@TestConfiguration
// @ComponentScan("some.package.mapper")
@ComponentScan(basePackageClasses = DtoMapper.class)
public class MappersConfig {
}
But there is an obvious drawback in this (as well as accepted answer) approach: the whole package will be scanned which may contain undesired classes.但是这种(以及接受的答案)方法有一个明显的缺点:整个 package 将被扫描,其中可能包含不需要的类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.