1

I'm trying to test a method in service class which uses ModelMapper to convert dto to entity, but I'm getting NullPointerException at this line. how do i fix it?

Exception

java.lang.NullPointerException: Cannot invoke "org.modelmapper.ModelMapper.map(Object, java.lang.Class)" because the return value of "com.where.where.mapper.ModelMapperService.forRequest()" is null

at com.where.where.service.ScoreServiceTest.whenCreateScoreCalledWithValidRequest_itShouldReturnValidCreateScoreRequest(ScoreServiceTest.java:44)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

Test Class

public class ScoreServiceTest {

    private ScoreRepository scoreRepository;
    private ScoreService scoreService;
    private ModelMapperService modelMapperService;


    @BeforeEach
    void setUp() {
        scoreRepository = mock(ScoreRepository.class);
        modelMapperService = mock(ModelMapperService.class);
        scoreService = new ScoreService(scoreRepository,modelMapperService);
    }

    @Test
    void whenCreateScoreCalledWithValidRequest_itShouldReturnValidCreateScoreRequest() {
        CreateScoreRequest createScoreRequest = new CreateScoreRequest();
        createScoreRequest.setVenueScore(3);
        createScoreRequest.setCoronaScore(2);
        createScoreRequest.setCreateDate("17-3-2022");
        createScoreRequest.setPlaceId(1L);
        createScoreRequest.setUserId(1L);

        Score score = new Score();
        score.setId(1L);
        score.setCoronaScore(2);
        score.setVenueScore(3);
        score.setCreateDate("17-3-2022");
        
        when(modelMapperService.forRequest().map(org.mockito.ArgumentMatchers.any(), org.mockito.ArgumentMatchers.any())).thenReturn(score);
        when(score.getId()).thenReturn(1L);
        when(scoreRepository.save(ArgumentMatchers.any(Score.class))).thenReturn(score);

        Score result = scoreRepository.save(score);

        assertEquals(result,score);
    }
}

Score Service

@Service
@RequiredArgsConstructor
public class ScoreService {
    private final ScoreRepository scoreRepository;
    private final ModelMapperService modelMapperService;

    public CreateScoreRequest add(CreateScoreRequest createScoreRequest) {
        Score score = modelMapperService.forRequest().map(createScoreRequest, Score.class);
        scoreRepository.save(score);
        return createScoreRequest;
    }

    public List<ScoreDto> getAll() {
        List<Score> result = scoreRepository.findAll();
        List<ScoreDto> response = result.stream().map(score -> modelMapperService.forDto().map(score, ScoreDto.class))
                .collect(Collectors.toList());
        return response;
    }

    public ScoreDto getById(Long id) {
        Score score = scoreRepository.getById(id);
        ScoreDto response = modelMapperService.forDto().map(score, ScoreDto.class);
        return response;
    }

    public void delete(Long id) {
        scoreRepository.deleteById(id);
    }

    public CreateScoreRequest update(Long id, CreateScoreRequest updateScoreDto) {
        if (scoreRepository.existsById(id)) {
            Score score = modelMapperService.forRequest().map(updateScoreDto, Score.class);
            score.setId(id);
            scoreRepository.save(score);
            return updateScoreDto;
        }
        throw new ScoreNotFoundException("Score does not found.");

    }
}

Mapper I am using this class.

import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;

@Service
@RequiredArgsConstructor
public class ModelMapperManager implements ModelMapperService {
    private final ModelMapper modelMapper;

    @Override
    public ModelMapper forDto() {
        this.modelMapper.getConfiguration().setAmbiguityIgnored(true).setMatchingStrategy(MatchingStrategies.LOOSE);
        return modelMapper;
    }

    @Override
    public ModelMapper forRequest() {
        this.modelMapper.getConfiguration().setAmbiguityIgnored(true).setMatchingStrategy(MatchingStrategies.STANDARD);
        return modelMapper;
    }
}
Leonardo
  • 2,439
  • 33
  • 17
  • 31

2 Answers2

1

You need one more mock, for modelMapperService.forRequest() to return.

So you might have

modelMapper = mock(ModelMapper.class);

and then you'll be able to write

when(modelMapperService.forRequest()).thenReturn(modelMapper);
when(modelMapper.map(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(score);

instead of trying to do the two steps all on one line.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
-1

Mocked object will return default values, in your case it will be null. Though it is not clear, it looks like your test class is not using any SpringRunner (no population of dependencies). Hence you are gettign NPE. You might be interested in spy objects than plain mocks. Please refer below link for more info

Mocking vs. Spying in mocking frameworks

Subhash
  • 71
  • 6
  • 1
    I don't see how using a spy would help the OP here. And there's certainly no need of a SpringRunner, or anything of that nature. This answer is not going to lead to a solution. – Dawood ibn Kareem Mar 21 '22 at 00:26
  • it depends on how you are writing testcase, what functionalities of dependency objects you need as it is or you want to mock. Based on that you can use plain mock objects or spy object. Link provided will explain more. – Subhash Mar 21 '22 at 01:35
  • 1
    Yes, but OP's question is very clear, their problem is very clear, and you're talking about things that are just completely irrelevant to their problem. They don't need a spy - it won't help them. They don't need a SpringRunner - that won't help them either. This answer might be helpful if the question were completely different. – Dawood ibn Kareem Mar 21 '22 at 01:47
  • sorry to disagree, but in my opinion, it is clear that OP is expecting mocked object to return something `modelMapperService.forRequest()`. OP is not getting why it is returning NULL. OP is lacking understanding of mocked object. That is where I am encouraging OP to learn more about Mocks vs Spys. If OP can understand it, OP will figure out solution, we don't need to do it. It is more about guiding OP. That is it. – Subhash Mar 21 '22 at 14:04