1

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

5
  • What exactly do you want to achieve? What does "use a real mapper method" mean? Commented Feb 6, 2023 at 8:40
  • please confirm if the listOfCardEntities in your test class is empty or have values Commented Feb 6, 2023 at 8:42
  • @Z-100 mainly i want to test this part of the method with listOfCardEntities (i give it through mock) listOfEntities.stream().filter(validationService::isCardExpired) .forEach(userCard -> userCard.setBlocked(true)); Then i want mapper maps the result as it would do in any usual case, when we call the method out of tests. It should return List<CardDto> with 4 elements, but i always get 0 Commented Feb 6, 2023 at 8:51
  • @idelkaro As far as I know, you can just annotate private MyMapper myMapper with @Mock and Mockito just creates an instance of that variable and inserts it into MyServiceImpl. Btw. Have you used a Debugger before? That would come in pretty handy here I think. And btw^2: Could you maybe provide us with your Mapper? (Not the impl) Commented Feb 6, 2023 at 8:57
  • @SpringLeaner, showed setUp method Commented Feb 6, 2023 at 9:02

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.