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

映射器定义中的可模仿spring依赖注入

叶坚
2023-03-14

我需要从一个自定义映射方法访问一个Spring bean。但是在单元测试映射方法时,我还需要能够注入Spring bean的模拟。

下面是我的映射器类的一个最小示例

@Mapper(componentModel = "spring")
public abstract class MyMapper {
    private final MyBean myBean;
    
    public MyMapper(MyBean myBean) {
        this.myBean = myBean;
    }

    @BeforeMapping
    protected MyElement initElement(MyElementDto dto) {
        // custom logic using the injected MyBean to initialize MyElement
    }
    
    public abstract MyElement map(MyElementDto dto);
}

@Component
public class MyMapperImpl extends MyMapper {
    @Autowired
    public MyMapperImpl(MyBean myBean) {
        super(myBean);
    }

    // ... mapping function implementation ...
}

因此,问题是:如何以最干净的方式实现这种类型的逻辑,以便生成的映射器实现是单元可测试的,并且可以正确地模拟MyBean依赖关系?

使用MapStruct 1.3.0、Final、Spring 4.3.25、Release、Mockito 1.9.5和Junit 4.12。

共有1个答案

冯新知
2023-03-14

通过使用@objectfactory而不是@beforemapping进行元素初始化,找到了这种情况的解决方案。这也带来了更好的代码结构、关注点分离和可测试性。

元素初始化逻辑将在单独的Spring bean中定义

@Component
public class MyFactory {
    private final MyBean myBean;

    @Autowired
    public MyFactory(MyBean myBean) {
        this.myBean = myBean;
    }

    @ObjectFactory
    public MyElement initialize(MyElementDto dto) {
        // custom logic using the injected MyBean to initialize MyElement
    }
}

上面的组件可以单独测试,模拟和注入MyBean

@Mapper(componentModel = "spring",
        uses = MyFactory.class,
        injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface MyMapper {
    MyElement map(MyElementDto dto);
}
/** THIS IS AUTOMATICALLY GENERATED CODE **/
@Component
public class MyMapperImpl implements MyMapper {
    private final MyFactory myFactory;

    @Autowired
    public MyMapperImpl(MyFactory myFactory) {
        this.myFactory = myFactory;
    }

    @Override
    public MyElement map(MyElementDto dto) {
        if ( dto == null ) {
            return null;
        }

        MyElement myElement = myFactory.initialize( dto ); // <-- FACTORY USED HERE

        // ... field mapping code here, after initialization ...

        return myElement;
    }
}

通过模拟和注入MyFactory,映射器很容易进行单元测试。我想避免加载任何Spring上下文,所以我手动初始化了MyFactoryImpl实例。

@RunWith(MockitoJUnitRunner.class)
public class MyMapperTest {
    @Mock
    private MyFactory myFactory;
    
    private MyMapper myMapper;
    
    @Before
    public void setUp() {
        // ... myFactory stubs ...
        
        myMapper = new MyMapperImpl(myFactory);
    }
    
    // ... tests ...
}
 类似资料:
  • 我尝试用Spring-Boot创建一个spring web应用程序。我的第一个问题是依赖注入对我不起作用。这是我跟踪的那篇文章。 我创建了一个应用程序类: 我的分级文件: 我所期望的:当我打开/greeting页面时,将出现log,但我在的开头得到了这一点: 2017-09-12 10:47:56.058警告7545--[main]ConfigEmbeddedWebApplicationConte

  • 以下是我的上下文:我使用byteBuddy动态生成一个类,该类根据外部配置将一个对象转换为另一个对象。我遇到了一些问题,我想找到一个替代方案,这就是我发现MapStruct的方式。 因此,我试图构建简单的映射器,我想知道是否有可能自定义注释以添加转换函数。例如,我想要: 在mapper实现中,我会有如下内容: 如果有人能帮我做到这一点,我将不胜感激,这将节省我很多时间。 提前谢谢。

  • 我使用MapStruct来映射我的实体,我使用Mockito来嘲笑我的对象。 我想用MapStruct测试一个包含映射的方法。问题是嵌套映射器在我的单元测试中总是为null(在应用程序中工作得很好)

  • 我有两个对象,除了date成员外,其他成员都相同。在obj1中,date是java.sql.date,obj2.date是long(纪元)。 我需要编写一个映射器来将obj1映射到obj2。这就是我试图做的: 但是mapperImpl只有自己的日期转换实现: 我得到了: 这种转换的正确方式是什么?

  • 在本章中,您将学习如何使用Aurelia依赖注入库。 首先,我们需要在src文件夹中创建新的文件dependency-test.js 。 在这个文件中,我们将创建一个简单的类DependencyTest 。 该类稍后将作为依赖项注入。 src/dependency-test.js export class DependencyTest { constructor() { this

  • 我正在编写一个应用程序,该应用程序与一个数据库通信,获取其他数据库的凭据,并连接到其他数据库。它使用在运行时构造的数据源和实体管理器工厂来执行此操作。 如果我想使用Spring Data Repositories,我想我需要自动连接它们,因此它们必须是Spring Beans。 如果在对第一个数据库运行查询之前没有构造的DataSource,我如何使用Spring Data?