简体   繁体   中英

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?

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

}

You need to mock all the dependencies that your test subject is using. You may want to do this in your AccountServiceTest class:

@Mock 
private BlogRepository blogRepositoryMock;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM