Mockito NullPointerException - Not recognizing repository - java

I'm having trouble figuring out why Mockito is throwing a NullPointerException when I'm telling the mock to return true.
Here is my JUnit Test:
public class PizzaValidatorTest {
private Pizza meatPizza;
private PizzaValidator validator = new PizzaValidator();
#MockBean
private IngredientRepository ingredientRepository;
#MockBean
private PizzaSizeRepository pizzaSizeRepository;
#Before
public void setUp() throws Exception {
meatPizza = new Pizza();
validator = new PizzaValidator();
}
#Test
public void validateValid() {
when(ingredientRepository.existsById(any())).thenReturn(true);
when(pizzaSizeRepository.existsById(any())).thenReturn(true);
assertTrue(validator.validate(meatPizza));
}
}
The PizzaValidator class is implemented below:
#Controller
public class PizzaValidator implements Validator<Pizza> {
#Autowired
IngredientRepository ingredientRepository;
#Autowired
PizzaSizeRepository pizzaSizeRepository;
#Override
public boolean validate(Pizza entity) {
return validatePizza(entity);
}
private boolean validatePizza(Pizza pizza) {
return validPizzaSize(pizza) && validIngredients(pizza);
}
private boolean validPizzaSize(Pizza pizza) {
return pizzaSizeRepository.existsById(pizza.getSizeDesc().getId());
}
private boolean validIngredients(Pizza pizza) {
for (Ingredient ingredient : pizza.getIngredients()) {
if (!ingredientRepository.existsById(ingredient.getId())) {
return false;
}
}
return true;
}
}
For some reason it seems like Mockito isn't connecting the mock repository with my class repository, but I can't figure out why. Any help is appreciated. Thanks.

You should not create the PizzaValidator using new keyword, you should #Autowire it in the test
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class PizzaValidatorTest {
private Pizza meatPizza;
#Autowire
private PizzaValidator validator;
#MockBean
private IngredientRepository ingredientRepository;
#MockBean
private PizzaSizeRepository pizzaSizeRepository;
#Before
public void setUp() throws Exception {
meatPizza = new Pizza();
}
#Test
public void validateValid() {
when(ingredientRepository.existsById(any())).thenReturn(true);
when(pizzaSizeRepository.existsById(any())).thenReturn(true);
assertTrue(validator.validate(meatPizza));
}
}

Related

How to mock model in service test?

I try write service test, for example, I have this ExamServiceImpl:
#Service
public class ExamServiceImpl implements ExamService {
#Autowired
private final SubjectService scoreService;
private final ScoreDAO scoreDAO;
#Autowired
public ExamServiceImpl(ScoreDAO scoreDAO) {
this.scoreDAO = scoreDAO;
}
#Override
public ResponseModel insertScore(RequestModel request) throws IOException {
SubjectModel subject = scoreService.getNameSubject(request);
ScoreModel score = new ScoreModel();
score.setStudentName(request.getStudentName);
score.setScore(request.getStudentScore);
score.setSubject(subject.getName);
int result = scoreDAO.insert(score);
return result;
}
}
Sample my test:
#SpringBootTest
public class ExamServiceImplTest {
#MockBean
private ScoreDAO scoreDAO;
#Autowired
private SubjectService subjectService;
#Autowired
private ExamService examService;
#Test
void insertScoreTest() {
SubjectModel resFromSubject = new SubjectModel();
resFromSubject.setSubject("Math");
Mockito.when(subjectService.getNameSubject(new RequestModel())).thenReturn(resFromSubject);
Mockito.when(scoreDAO.insert(new ScoreModel())).thenReturn(1);
int resultTest = examService.insertScore(new RequestModel());
assertSame(ex, 1);
}
But output resultTest is 0. I try debugger, I found mock scoreDAO.insert() return 0 >> is not working.
And I try like this:
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
public class ExamServiceImplTest {
#Mock
private ScoreDAO scoreDAO;
#Mock
private SubjectService subjectService;
#InjectMocks
private ExamService examService = ExamServiceImpl(scoreDAO);
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
void insertScoreTest() {
SubjectModel resFromSubject = new SubjectModel();
resFromSubject.setSubject("Math");
Mockito.when(subjectService.getNameSubject(new RequestModel())).thenReturn(resFromSubject);
Mockito.when(scoreDAO.insert(new ScoreModel())).thenReturn(1);
int resultTest = examService.insertScore(new RequestModel());
assertSame(ex, 1);
}
It's not work too.
Please, could you help write me test methods? I covered with tests more simple other services.
Thank you!
It doesn't work because new ScoreModel() inside Mockito.when() and inside ExamServiceImpl are two different objects. If you want scoreDAO to return 1 for every ScoreModel passed to it you can use:
Mockito.when(scoreDAO.insert(Mockito.any(ScoreModel.class)).thenReturn(1);

Q:Mockito - Using #Mock and #Autowired

I'd like to test a service class which has two other service classes like as below using Mockito.
#Service
public class GreetingService {
private final Hello1Service hello1Service;
private final Hello2Service hello2Service;
#Autowired
public GreetingService(Hello1Service hello1Service, Hello2Service hello2Service) {
this.hello1Service = hello1Service;
this.hello2Service = hello2Service;
}
public String greet(int i) {
return hello1Service.hello(i) + " " + hello2Service.hello(i);
}
}
#Service
public class Hello1Service {
public String hello(int i) {
if (i == 0) {
return "Hello1.";
}
return "Hello1 Hello1.";
}
}
#Service
public class Hello2Service {
public String hello(int i) {
if (i == 0) {
return "Hello2.";
}
return "Hello2 Hello2.";
}
}
I know how to mock Hello1Service.class and Hello2Service.class with Mockito like as below.
#RunWith(MockitoJUnitRunner.class)
public class GreetingServiceTest {
#InjectMocks
private GreetingService greetingService;
#Mock
private Hello1Service hello1Service;
#Mock
private Hello2Service hello2Service;
#Test
public void test() {
when(hello1Service.hello(anyInt())).thenReturn("Mock Hello1.");
when(hello2Service.hello(anyInt())).thenReturn("Mock Hello2.");
assertThat(greetingService.greet(0), is("Mock Hello1. Mock Hello2."));
}
}
I'd like to mock Hello1Service.class and inject Hello2Service.class using #Autowired like as below.
I tired to use #SpringBootTest but it did not work.
Is there a better way?
#RunWith(MockitoJUnitRunner.class)
public class GreetingServiceTest {
#InjectMocks
private GreetingService greetingService;
#Mock
private Hello1Service hello1Service;
#Autowired
private Hello2Service hello2Service;
#Test
public void test() {
when(hello1Service.hello(anyInt())).thenReturn("Mock Hello1.");
assertThat(greetingService.greet(0), is("Mock Hello1. Hello2."));
}
}
You want to inject dependency with some functionality to be formed then use #Spy.
You don't to load Spring Container and use #Autowired.
#Spy
private Hello2Service hello2Service=new Hello2Service();
You can read more detail about Mock vs Spy ;
https://dzone.com/articles/mockito-mock-vs-spy-in-spring-boot-tests
You can change with Spy for real object instead of Mock.
Test code will be like this;
#RunWith(MockitoJUnitRunner.class)
public class GreetingServiceTest {
#InjectMocks
private GreetingService greetingService;
#Mock
private Hello1Service hello1Service;
#Spy
private Hello2Service hello2Service;
#Test
public void test() {
when(hello1Service.hello(anyInt())).thenReturn("Mock Hello1.");
assertThat(greetingService.greet(0), is("Mock Hello1. Hello2."));
}
}

Unable to call the function from the mocked component class

I have a junit test method as follows:
#SpringBootTest
public class StoreIdAssignmentServiceTest {
private static final Logger log = LoggerFactory
.getLogger(StoreIdAssignmentServiceTest.class);
#InjectMocks
private StoreIdAssignmentService storeIdAssignmentService;
#Mock
private StoreIdAssignmentFactory storeIdAssignmentFactory;
#Mock
private DatabaseService databaseService;
#Test
public void rollUpFeed_Single_DealerAndStoreID_NoExisting() {
List<ScmsaPosTransRollup> scmsaPosTransRollupFeedList = new ArrayList<>();
ScmsaPosTransRollup posTransRollup = new ScmsaPosTransRollup();
posTransRollup.setJobLogId(8269726L);
posTransRollup.setDealerCode("3119255");
posTransRollup.setStoreId("9842");
posTransRollup.setTransactionDate(Timestamp
.valueOf("2018-03-01 13:00:00.00"));
posTransRollup.setQuantity(4);
posTransRollup.setRollupType("H");
scmsaPosTransRollupFeedList.add(posTransRollup);
Mockito.when(
databaseService.getUnProcessedRollUpFeedBasedonRollupType("H"))
.thenReturn(scmsaPosTransRollupFeedList);
List<PosHourlySt> existingPosHourlyStEntries = new ArrayList<>();
Mockito.when(databaseService.getDealerCodeFromPosHourly("3119255"))
.thenReturn(existingPosHourlyStEntries);
Mockito.when(databaseService.getDealerCodeFromPosHourly("3119255"))
.thenReturn(existingPosHourlyStEntries);
storeIdAssignmentService.processHourlyStateFeed();
assertNotNull(posHourlyStRepository.findAll());
}
}
And My StoreIdAssignmentService class will be:
#Service
public class StoreIdAssignmentService {
private StoreIdAssignmentFactory storeIdAssignmentFactory;
private DatabaseService databaseService;
#Autowired
public StoreIdAssignmentService(StoreIdAssignmentFactory storeIdAssignmentFactory,
DatabaseService databaseService) {
this.storeIdAssignmentFactory = storeIdAssignmentFactory;
this.databaseService = databaseService;
}
public void processHourlyStateFeed() {
.......................
calculateStateForPosHourlyStTransaction(posHourlyStToConsider, newPosHourlyStEntries);
.........
}
List<ScmsaPosTransRollup> scmsaPosTransRollupUpdatedFlagList = storeIdAssignmentFactory
.createUpdatedRollUpEntries(rollUpFeedByDealerCode);
saveAndUpdatePosHourlyStAndRollUpEntries(newPosHourlyStEntries, existingPosHourlyStEntries,
rollUpFeedByDealerCode, scmsaPosTransRollupUpdatedFlagList);
}
}
private Map<String, List<ScmsaPosTransRollup>> groupDealerCodeRollUpFeedByStoreId(
List<ScmsaPosTransRollup> rollUpFeedByDealerCode) {
// Grouping the rollUpFeedByDealerCode by storeID
return rollUpFeedByDealerCode.stream().collect(Collectors.groupingBy(ScmsaPosTransRollup::getStoreId));
}
private void calculateStateForPosHourlyStTransaction(ScmsaPosTransRollup scmsaPosTransRollupToConsider, List<PosHourlySt> newPosHourlyStEntries) {
List<PosHourlySt> posHourlyStList = newPosHourlyStEntries.stream().filter(
hourlyState -> (hourlyState.getStartDate().before(scmsaPosTransRollupToConsider.getTransactionDate())))
.collect(Collectors.toList());
..............
PosHourlySt posHourlySt=storeIdAssignmentFactory.createHourlyStEntryFromRollUp(scmsaPosTransRollupToConsider,
Timestamp.valueOf(scmsaPosTransRollupToConsider.getTransactionDate().toLocalDateTime().withHour(0).withMinute(0)),
Timestamp.valueOf(scmsaPosTransRollupToConsider.getTransactionDate().toLocalDateTime().withHour(23).withMinute(59)));
newPosHourlyStEntries.add(posHourlySt);
....................
}
}
and My Factory class would be:
#Component
public class StoreIdAssignmentFactory {
private static final Logger log = LoggerFactory.getLogger(StoreIdAssignmentFactory.class);
private ModelMapper modelMapper;
#Autowired
public StoreIdAssignmentFactory(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
}
public PosHourlySt createHourlyStEntryFromRollUp(ScmsaPosTransRollup scmsaPosTransRollup, Timestamp startDate, Timestamp endDate){
PosHourlySt posHourlySt = new PosHourlySt();
posHourlySt.setDealerCode(scmsaPosTransRollup.getDealerCode());
posHourlySt.setSourceJobLogId(scmsaPosTransRollup.getJobLogId());
posHourlySt.setStartDate(startDate);
posHourlySt.setStoreId(scmsaPosTransRollup.getStoreId());
posHourlySt.setEndDate(endDate);
posHourlySt.setJobLogId(0L);
posHourlySt.setSource("ROLLUP");
log.info("New Rec: {}", posHourlySt.toString());
return posHourlySt;
}
public PosHourlySt createHourlyStEntryFromPosHourlySt(PosHourlySt posHourlyStToSplit, Timestamp endDate){
PosHourlySt posHourlySt = new PosHourlySt();
posHourlySt.setDealerCode(posHourlyStToSplit.getDealerCode());
posHourlySt.setSourceJobLogId(posHourlyStToSplit.getJobLogId());
posHourlySt.setStartDate(posHourlyStToSplit.getStartDate());
posHourlySt.setStoreId(posHourlyStToSplit.getStoreId());
posHourlySt.setEndDate(endDate);
posHourlySt.setJobLogId(0L);
posHourlySt.setSource("ROLLUP");
log.info("SplitupRec: {}", posHourlySt.toString());
return posHourlySt;
}
public List<ScmsaPosTransRollup> createUpdatedRollUpEntries(List<ScmsaPosTransRollup> rollUpFeedByDealerCode) {
List<ScmsaPosTransRollup> scmsaPosTransRollupUpdatedFlagList = new ArrayList<>();
for(ScmsaPosTransRollup scmsaPosTransRollupFeed : rollUpFeedByDealerCode) {
ScmsaPosTransRollup scmsaPosTransRollupUpdateFlag = new ScmsaPosTransRollup();
modelMapper.map(scmsaPosTransRollupFeed, scmsaPosTransRollupUpdateFlag);
scmsaPosTransRollupUpdateFlag.setProcessedFlag("Y");
scmsaPosTransRollupUpdatedFlagList.add(scmsaPosTransRollupUpdateFlag);
}
return scmsaPosTransRollupUpdatedFlagList;
}
}
The StoreIdAssignmentService class contains the method "calculateStateForPosHourlyStTransaction" which calls some method in Factory class. When I debug as the junit test case , am not able to call that factory class method . What I am doing wrong here. Can anyone please suggest me.
You are mocking the factory:
#Mock
private StoreIdAssignmentFactory storeIdAssignmentFactory;
So you can't investigate the method createHourlyStEntryFromRollUp inside the factory, because the whole factory is mocked:
storeIdAssignmentFactory.createHourlyStEntryFromRollUp
If you trying to debug the createHourlyStEntryFromRollUp and the StoreIdAssignmentFactory is a #Component (or #Service), I recommend create a StoreIdAssignmentFactoryTest class test, use the #Autowired on it and #MockBean his dependencies.
Example:
#SpringBootTest
public class StoreIdAssignmentFactoryTest {
#Autowired
StoreIdAssignmentFactory factory;
#Test
public void testing() {
List<ScmsaPosTransRollup> list = factory.createHourlyStEntryFromRollUp(...);
//TODO asserts and etc
}
}
But this test is considered a integration test, because it load the whole spring context and beans related.
Another alternative is the (true) unit test. Use your constructor and not use #SpringBootTest, mock the dependencies (ModelMapper). This makes the test more fast and simple.
Example:
public class StoreIdAssignmentFactoryTest {
#Test
public void testing() {
ModelMapper mapper = mock(ModelMapper.class);
StoreIdAssignmentFactory factory = new StoreIdAssignmentFactory(mapper)
List<ScmsaPosTransRollup> list = factory.createHourlyStEntryFromRollUp();
//TODO asserts and etc
}
}

Failing to mock #Autowired Object

I am using Junit4 and Mockito for test cases, in the following code I am trying to mock a autowired object which throws null pointer exception inside the mocking class which means autowired object is not mocking properly
ContentDao.java
public class ContentDao {
#Autowired
private ConfigProperties configProperties;
public void fuction() {
int batchSize = configProperties.getBatchSize();
}
ConfigProperties.java
#ConfigurationProperties(ignoreUnknownFields = false, prefix = "cleanup")
public class ConfigProperties {
private int batchSize;
public int getBatchSize() {
return batchSize;
}
}
Trying to mock ConfigProperties.
#RunWith(MockitoJUnitRunner.class)
public class ContentDaoTest{
#InjectMocks
private ContentDao contentDao;
#Mock
private ConfigProperties configProperties;
#Test
public void functionTest(){
configProperties = mock(ConfigProperties.class);
when(configProperties.getBatchSize()).thenReturn(100);
ContentDao contentDao = new ContentDao();
contentDao.funtion();
}
funtion is called, but I get NPE in below line. Please help I am stuck here.
int batchSize = configProperties.getBatchSize();
If you set #Mock for configProperties, you should not mock again configProperties = mock(ConfigProperties.class);
In the same idea, as you set #InjectMocks for contentDao, you should not instantiate a new contentDao.
#RunWith(MockitoJUnitRunner.class)
public class ContentDaoTest {
#InjectMocks
private ContentDao contentDao;
#Mock
private ConfigProperties configProperties;
#Test
public void functionTest() {
Mockito.when(configProperties.getBatchSize()).thenReturn(100);
Assertions.assertThat(contentDao.getBatchSize()).isEqualTo(100);
}
}

Using autowired dependencies with certain mock dependency in Spring4

I have a rest resource for signup and login. both in a controller class. the controller class has a dependency to a service class with the business logic. the service class has further dependencies. cause i use an embedded db for testing, i want to use the real dependencies of my app instead to mock them with something like #injectmock #mock. there is only one certain dependency i have to mock. its the dependency for sending emails after a signup process. how to write test cases with #autowired function and one certain mock dependency for email notification?
#Controller
public class AccountCommandsController {
#Autowired
private LogoutService service;
#RequestMapping(value = "/rest/login", method = RequestMethod.POST)
public ResponseEntity login(#RequestBody Account account) {
AccountLoginEvent accountLoginEvent = service.loginAccount(new RequestAccountLoginEvent(account.getEmailAddress(), account.getPassword()));
if (accountLoginEvent.isLoginGranted()) {
return new ResponseEntity(HttpStatus.ACCEPTED);
} else {
return new ResponseEntity(HttpStatus.UNAUTHORIZED);
}
}
#RequestMapping(value = "/rest/signup", method = RequestMethod.POST)
public ResponseEntity signup(#RequestBody Account account) {
AccountSignupEvent signedupEvent = service.signupAccount(new RequestAccountSignupEvent(account.getEmailAddress(), account.getPassword()));
if (signedupEvent.isSignupSuccess()) {
return new ResponseEntity(HttpStatus.ACCEPTED);
} else if (signedupEvent.isDuplicateEmailAddress()) {
return new ResponseEntity(HttpStatus.CONFLICT);
} else if (signedupEvent.isNoSignupMailSent()) {
return new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);
} else {
return new ResponseEntity(HttpStatus.FORBIDDEN);
}
}
}
#Service
public class LogoutService {
#Autowired
private AccountsRepository accountsRepository;
#Autowired
private MailService mailService;
#Autowired
private HashService hashService;
public AccountSignupEvent signupAccount(RequestAccountSignupEvent signupEvent) {
if (accountsRepository.existEmailAddress(signupEvent.getEmailAddress())) {
return AccountSignupEvent.duplicateEmailAddress();
}
Account newAccount = new Account();
newAccount.setCreated(new Date());
newAccount.setModified(new Date());
newAccount.setEmailAddress(signupEvent.getEmailAddress());
newAccount.setPassword(signupEvent.getPassword());
newAccount.setVerificationHash(hashService.getUniqueVerificationHash());
SignupMailEvent mailSentEvent = mailService.sendSignupMail(new RequestSignupMailEvent(newAccount));
if (!mailSentEvent.isMailSent()) {
return AccountSignupEvent.noMailSent();
}
Account persistedAccount = accountsRepository.persist(newAccount);
return AccountSignupEvent.accountCreated(persistedAccount);
}
public AccountLoginEvent loginAccount(RequestAccountLoginEvent loginEvent) {
if (accountsRepository.existLogin(loginEvent.getEmailAddress(), loginEvent.getPassword())) {
return AccountLoginEvent.granted();
}
return AccountLoginEvent.denied();
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestConfiguration.class)
#Transactional
#TransactionConfiguration(defaultRollback = true)
public class LogoutTest {
private MockMvc mockMvc;
#Autowired
private AccountCommandsController controller;
#Before
public void setup() {
mockMvc = standaloneSetup(controller).build();
}
#Test
public void signupNoMail() throws Exception {
doReturn(AccountSignupEvent.noMailSent()).when(service).signupAccount(any(RequestAccountSignupEvent.class));
// when(controller.service.signupAccount(any(RequestAccountSignupEvent.class))).thenReturn(AccountSignupEvent.noMailSent());
mockMvc.perform(post("/rest/signup")
.content(new Gson().toJson(new Account(UUID.randomUUID().toString(), UUID.randomUUID().toString())))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isServiceUnavailable());
}
}
I hope you see the problem. Every dependency works fine instead mailservice. I dont want to use #injectmock and #mock with MockitoAnnotations.initMocks(this); in my test file, because of the neccessary to provide for all dependencies mocks.
if your dependencies are running and you have a configuration class where you have defined the endpoint, you can use ConfigurableApplicationContext class, something like this:
public class test {
private static ConfigurableApplicationContext appContext;
private LogoutService service;
#AfterClass
public static void destroy() {
appContext.close();
}
#Before
public void setup() {
appContext = new AnnotationConfigApplicationContext(YourClassConfig.class);
service = appContext.getBean(LogoutService.class);
}
#Test
public void beansAreCreated() {
assertNotNull(service);
}
}
Or you can re-write your endpoint with a configuration class and you can use WireMock (http://wiremock.org) to emulate your dependency with real data, this should be something like this:
public class test {
#Rule
public WireMockRule wireMockRule = new WireMockRule(15000);
private static ConfigurableApplicationContext appContext;
private LogoutService service;
private static String serviceMockUrl;
#AfterClass
public static void destroy() {
appContext.close();
}
#Before
public void setup() {
serviceMockUrl = "http://localhost:" + wireMockRule.port();
appContext = new AnnotationConfigApplicationContext(TestConfig.class);
stubFor(get(urlEqualTo("urlToRequest")).
willReturn(aResponse().
withStatus(SC_OK).
withBody(createJsonArray("MapWithYourData").
withHeader("Content-Type", "application/json")));
service = appContext.getBean(LogoutService.class);
}
#Test
public void beansAreCreated() {
assertNotNull(service);
}
#Configuration
static class TestConfig {
#Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertyPlaceholderConfigurer() {{
setProperties(new Properties() {{
setProperty("service.url", serviceMockUrl);
}});
}};
}
}
}
I hope this help you.
What you are trying to do is easily implemented using Spring Profiles.
On way to achieve it is the following:
#Configuration
public class TestConfiguration {
//this is the real mail service
#Bean
public MailService mailService() {
return new MailService(); //or whatever other bean creation logic you are using
}
//whatever else
}
#Configuration
#Profile("mockMail")
public class MockMailServiceConfig {
#Bean
#Primary
public MailService mockMailService() {
return mock(MailService.class);
}
}
Your test class would then look like:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestConfiguration.class)
#Transactional
#TransactionConfiguration(defaultRollback = true)
#ActiveProfiles("mockMail")
public class LogoutTest {
//do your testing
}
Note the use of #Primary in MockMailServiceConfig. I opted for this way since it wouldn't require you to introduce profiles anywhere else if you are not already using them. #Primary tells spring to use that specific bean if multiple candidates are available (in this case there is the real mail service and the mock service)

Categories

Resources