如何在测试中使用真实的MapStruct映射器方法?

huangapple go评论61阅读模式
英文:

How to use a real mapstruct mapper method in test?

问题

我有一个类,其中一个方法中使用了映射器来将结果返回为DTO列表。我想使用一个真正的映射器方法,因为它可以让我检查真实的功能。

这是我的测试类:

@ExtendWith(MockitoExtension.class)
public class UserCardServiceTest {

    @Mock
    private MyCardRepository myCardRepository;

    @Mock(answer = Answers.CALLS_REAL_METHODS)
    private MyMapper myMapper;

    @InjectMocks
    private MyServiceImpl underTest;
    
    // ...其他部分...
}

我要测试的方法如下:

@RequiredArgsConstructor
public class MyServiceImpl implements MyCardService {

    private final MyCardRepository myCardRepository;

    private final MyMapper myMapper;

    @Override
    public List<CardDto> getActiveUserCardsById(final long userId) {
       
        List<CardEntity> listOfEntities = myRepository.findAllByUserId(userId);

        listOfEntities.stream().filter(validationService::isCardExpired)
                .forEach(userCard -> userCard.setBlocked(true));

        List<CardEntity> sorted = listOfEntities.stream()
                .sorted(o -> o.getName().toUpperCase())
                .toList();

        return myMapper
                .listOfCardEntitiesToCardDto(sorted);
    }
}

但是,我得到以下结果:

java.lang.AssertionError: 
Expected size: 4 but was: 0 in:
[]

有人能否告诉我如何调用一个真正的MapStruct映射器方法,而不是准备好的答案。是否可以只使用@ExtendWith(MockitoExtension.class)来实现?

【注意】:上述代码示例中的 "<" 和 ">" 字符是 HTML 实体编码,用于表示尖括号 "<" 和 ">"。在实际代码中应使用正常的尖括号。

英文:

I have a class that uses mapper in one of the methods to return the result as a list of DTOs.
I want to use a real mapper method as it gives me possibility to check real functionality.

It's my test class:

@ExtendWith(MockitoExtension.class)
public class UserCardServiceTest {

    @Mock
    private MyCardRepository myCardRepository;

    @Mock(answer = Answers.CALLS_REAL_METHODS)
    private MyMapper myMapper;

    @InjectMocks
    private MyServiceImpl underTest;
    
 @BeforeEach
    void setUp() {
      listOfExpiredUserCardEntities = new ArrayList&lt;&gt;(List.of(
                getValidUserCardEntity()
                        .setExpirationDate(LocalDate.now().minusDays(1))
                        .setBlocked(false),
                getValidUserCardEntity()
                       .setExpirationDate(LocalDate.now().minusWeeks(1))
                        .setBlocked(false),
                    
                getValidUserCardEntity()
                        .setExpirationDate(LocalDate.now().minusYears(1))
                        .setBlocked(false),
                getValidUserCardEntity()
                    .setExpirationDate(LocalDate.now().minusMonths(1))
                        .setBlocked(false));
              }

 @Test
    void shouldChangeStatusIfCardExpired() {
        
        given(myCardRepository.findAllByUserId(1L))
                .willReturn(listOfCardEntities);
        
        assertThat(underTest.getActiveUserCardsById(1L)).isNotNull().hasSize(4);
        assertThat(underTest.getActiveUserCardsById(1))
                .extracting(CardDto::isBlocked)
                .containsExactly(true, true, true, true)
                .doesNotContainNull();
    }

My method to test:

@RequiredArgsConstructor
public class MyServiceImpl implements MyCardService {

    private final MyCardRepository myCardRepository;

    private final MyMapper myMapper;

    @Override
    public List&lt;CardDto&gt; getActiveUserCardsById(final long userId) {
       
        List&lt;CardEntity&gt; listOfEntities = myRepository.findAllByUserId(userId);

        listOfEntities.stream().filter(validationService::isCardExpired)
                .forEach(userCard -&gt; userCard.setBlocked(true));

        List&lt;CardEntity&gt; sorted = listOfEntities.stream()
                .sorted(o -&gt; o.getName().toUpperCase())
                .toList();

        return myMapper
                .listOfCardEntitiesToCardDto(sorted);
    }

But as a result I get:

java.lang.AssertionError: 
Expected size: 4 but was: 0 in:
[]

Can anyone say how to invoke a real mapstruct mapper method, but not prepared answer.
Is it possible to do with only @ExtendWith(MockitoExtension.class)?

答案1

得分: 1

我在我的项目中也遇到了相同的问题。我使用了以下解决方案:

import org.mapstruct.factory.Mappers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;

......

@Mock
private MyCardRepository myCardRepository;

@Spy
private MyMapper myMapper = Mappers.get(MyMapper.class);

@InjectMocks
private MyServiceImpl underTest;

这只需使用 @ExtendWith(MockitoExtension.class) 即可正常工作,无需启动整个SpringBoot上下文 如何在测试中使用真实的MapStruct映射器方法?

英文:

I had the same problem in my projects. I am using the following solution:

import org.mapstruct.factory.Mappers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;

.....

@Mock
private MyCardRepository myCardRepository;

@Spy
private MyMapper myMapper = Mappers.get(MyMapper.class);

@InjectMocks
private MyServiceImpl underTest;

This works with only @ExtendWith(MockitoExtension.class). There is no need to start the entire SpringBoot Context 如何在测试中使用真实的MapStruct映射器方法?

huangapple
  • 本文由 发表于 2023年2月6日 16:23:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75358872.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定