idelkaro
idelkaro

Reputation: 37

How to use a real mapstruct mapper method in test?

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<>(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<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);
    }

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)?

Upvotes: 0

Views: 728

Answers (1)

GJohannes
GJohannes

Reputation: 1753

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 ;)

Upvotes: 1

Related Questions