1

I am working on my first spring boot project and I am having trouble with testing my class as a Mockito newbie. I need to check that the findAndUpdateUser method below update User entity fields correctly :

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepo;

    public User findUser(String id) {
        return userRepo.findById(id);
    }

    public User findAndUpdateUser(String id) {
        User foundUser = findUser(id);
        //some update on foundUser fields
        return foundUser;
    }
}

To test, I need to mock entity bean because I don't have DB locally. Here is my test class :

@RunWith(MockitoJUnitRunner.class)
public class UpdateFieldsTest {
    @Mock
    private UserRepository userRepo;

    @Test
    public void test1() {
        User user = new User();
        user.setId("testId");
        //setting some other user fields

        Mockito.when(userRepo.findById("testId")).thenReturn(user);
        UserServiceImpl userService = new userServiceImpl();
        User returnedUser = userService.findAndUpdateUser("testId");

        //Checking if user field values are updated after findAndUpdate call
        Assert.xxx
        //other asserts
    }
}

But this code throw me some NullPointerException on method call. I even tried to mock findUser method but I still have error...

Am I having a bad approach ? How should I test my method ?

Any help is welcomed Thanks all

LostReality
  • 657
  • 2
  • 8
  • 33
  • 2
    1. Full stacktrace is usually helpful for debugging NPE. 2. You never infect that dependancy. You should pass `userRepo` into `userService` either via constructor or via a setter. – Amongalen Mar 18 '20 at 09:56
  • You're instanciating the `UserServiceImpl` which autowires a `UserRepository` I suppose? You cannot do it like that. If you don't let the framework handle the way your service is instanciated, the DI expressed through `@Autowired` annotations will not work. Probably the cause of the NPE. Mockito provides some mechanism to handle DI with mocked instances. You can take a look at `@InjectMocks` f.ex. – Imaguest Mar 18 '20 at 10:01
  • @Imaguest Yes exactly. I will check the InjectMocks annotation that i did not know. Thanks a lot ! – LostReality Mar 18 '20 at 10:05

2 Answers2

2

Mocks won't magicly appear inside of your object. You need to inject them manually. In you test, inside of the userService, the userRepo will be null. You inject dependancies either by constructor or by setter. It would look like this in your test:

UserServiceImpl userService = new userServiceImpl(userRepo);

Or

UserServiceImpl userService = new userServiceImpl();
userService.setUserRepo(userRepo);
Amongalen
  • 3,101
  • 14
  • 20
  • thanks, I am gonna try this – LostReality Mar 18 '20 at 10:02
  • can you share findAndUpdateUser function ? I guess, after calling findById, you call an other function (save, saveOrUpdate ...). In thiis case the second method return a null, you should mock it. – boukobba adil Mar 18 '20 at 10:17
  • findAndUpdateUser basically call findUser then update 1 user fields through setter (in this case user.setLastConsultDate(now()) & then return the object – LostReality Mar 18 '20 at 10:21
2

using this instantiation UserServiceImpl userService = new userServiceImpl(); make the UserRepo null;

you are using mockito, so you can use @InjectMocks private UserServiceImpl; and delete the instastiation line.

  • 1
    wow, thanks. So Mockito automatically bind UserRepo dependency to the corresponding service just through the annotation ! That's powerful ! Thanks again ! – LostReality Mar 18 '20 at 10:30