Elias Garcia Mariño Elias Garcia Mariño - 1 month ago 12
Java Question

Null pointer exception on @PostConstruct method?

I'm developing a small application in Java using Spring, so I have this Service:

public class AccountService implements UserDetailsService {

@Autowired
private AccountRepository accountRepository;

@Autowired
private BlogRepository blogRepository;

@Autowired
private ImageService imageService;

@PostConstruct
protected void initialize() throws IOException {
Account user = new Account("user", "demo", "ROLE_USER");
save(user);
Blog userBlog = new Blog("userBlog", true, user);
userBlog.setAvatar(imageService.createBlogAvatar(userBlog.getName()));
blogRepository.save(userBlog);
save(new Account("admin", "admin", "ROLE_ADMIN"));
}

// More methods

}


And this test:

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceTest {

@InjectMocks
private AccountService accountService = new AccountService();

@Mock
private AccountRepository accountRepositoryMock;

@Test
public void shouldInitializeWithTwoDemoUsers() throws IOException {
// act
accountService.initialize();
// assert
verify(accountRepositoryMock, times(2)).save(any(Account.class));
}

}


Why when I run the tests I get this exception?

shouldInitializeWithTwoDemoUsers(es.udc.fi.dc.fd.account.AccountServiceTest) Time elapsed: 0.016 sec <<< ERROR!
java.lang.NullPointerException: null
at es.udc.fi.dc.fd.account.AccountService.initialize(AccountService.java:45)
at es.udc.fi.dc.fd.account.AccountServiceTest.shouldInitializeWithTwoDemoUsers(AccountServiceTest.java:42)


Using the
@PostConstruct
annotation it's supposed to have all beans injected right?

Answer

Few things here. First of all @InjectMocks generally makes things easier but Mockito not a dependency injection framework, so its not guaranteed to work properly.

Secondly, for @InjectMocks to work properly you need to @Mock all your objects as well and not manually create the class you are trying to inject. I don't believe its the case anymore but in order versions of mockito, the order of the @Mocks would matter as well.

This code might work for you

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceTest {


    @Mock
    private AccountRepository accountRepositoryMock;

    @Mock
    private BlogRepository blogRepository;

    @Mock
    private ImageService imageService;

    @InjectMocks
    private AccountService accountService ;

    @Test
    public void shouldInitializeWithTwoDemoUsers() throws IOException {
        // act
        accountService.initialize();
        // assert
        verify(accountRepositoryMock, times(2)).save(any(Account.class));
    }

}
Comments