Mockito mock NullPointerException, don't know what else is there to try - java

Java thinks my mocked Course class object is null at the line when().thenReturn().
class StudentTest {
#Mock
Course courseMock1;
#Test
void student_getTeacherNames_should_return_list_of_full_names() {
when(courseMock1.getEAP()).thenReturn(1);
}
public class Course {
public Course(String courseName, String name, LocalDate startDate, LocalDate endDate, Integer EAP, Teacher teacher) {
this.courseName = courseName;
this.name = name;
this.startDate = startDate;
this.endDate = endDate;
this.EAP = EAP;
this.teacher = teacher;
}
public Integer getEAP() {
return EAP;
}
}
I have tried:
#RunWith(MockitoJUnitRunner.class)
class StudentTest{...
--
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
}
--
#Rule public Mocks mocks = new Mocks(this);
none of which solve NPE.
Also tried (using mocked Teacher object as one of the parameters)
#Mock
Course courseMock1 = new Course(params..);
which yielded:
MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'

Annotate StudentTest class with #RunWith(MockitoJUnitRunner.class).
Declare StudentTest class as public.
Declare student_getTeacherNames_should_return_list_of_full_names method as public.
Run the test class.
#RunWith(MockitoJUnitRunner.class)
public class StudentTest {
#Mock
Course courseMock1;
#Test
public void student_getTeacherNames_should_return_list_of_full_names() {
Mockito.when(courseMock1.getEAP()).thenReturn(1);
assertThat(courseMock1.getEAP()).isEqualTo(1);
}
}

What test framework are you using ? junit 4 or junit 5 ?
If junit5 , then the test class should be annotated with #ExtendWith(MockitoExtension.class)
An alternative could be to rely purely on code (not using annotation).
The code would become
class StudentTest {
Course courseMock1 = Mockito.mock(Course.class);
...
}

To use #Mock annotations you need to import org.mockito.MockitoAnnotations; and call MockitoAnnotations.initMocks. Note that the method has to be called before each test.
#BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
}
I used mistakenly #Before instead of #BeforeEach

Related

Guice: Inject class with constructor with own parameters?

I have a problem with Guice. I would like to show this with an example. I want to pass the parameters of this constructor always dynamically, so e.g. new Test("bob", 765);. I also want some fields (like here SomeOtherObject) to be injected by Guice. How can I do this? Thanks in advance!
public class Test {
private String name;
private int id;
//Needs to be injected by Guice
#Inject
SomeOtherObject object;
public Test(String name, int id) {
this.name = name;
this.id = id;
}
}
Guice's AssistedInject feature is a good way to handle this.
Basically you define a factory to get Test objects with:
public interface TestFactory {
public Test create(String name, int id);
}
Augment the Test class's #Inject constructor with #Assisted annotation:
public class Test {
#Inject
public Test(SomeOtherObject object, #Assisted String name, #Assisted int id) {
this.object = object;
this.name = name;
this.id = id;
}
}
And then use FactoryModuleBuilder in your Module's configure:
install(new FactoryModuleBuilder().build(TestFactory.class));
And instead of constructing Tests directly, inject a TestFactory and use it to create Tests:
public class OtherThing {
#Inject
TestFactory factory;
public Test doStuff(Stirng name, int id) {
return factory.create(name, id);
}
}
Note: looking at the docs now, it appears that AutoFactory has been introduced as the preferred way to do this, and may be simpler.

How to use Mockito to populate POJO

I have a POJO class:
#Data #Document
public class RoomPreferences{
private TypeEnum roomType;
private BigDecimal minLen;
private BigDecimal maxLen;
private List<BigDecimal> defaultPrices;
}
I want to populate a RoomPreferences object at test and I am using Mockito, but my RoomPreferences object's fields are always null.
public class TestingClass {
#Mock private RoomPreferences roomPreferences;
#InjectMocks public RoomServiceImpl roomService;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
when(roomPreferences.getMinLen()).thenReturn(BigDecimal.valueOf(10));
...
}
}
What I read out of this testing class:
public class TestingClass {
#Mock private RoomPreferences roomPreferences;
#InjectMocks public RoomServiceImpl roomService;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
when(roomPreferences.getMinLen()).thenReturn(BigDecimal.valueOf(10));
...
}
}
is that roomService of type RoomServiceImpl has an attribute of type RoomPreferences. And this attribute will be injected with the mocked object "roomPreferences".
The mocked object won't be populated with any value of the real class.
What you do is define what the mock should do when a method (as in the real class) is called on it:
when(roomPreferences.getMinLen()).thenReturn(BigDecimal.valueOf(10));
If you wan to assing a value to a property then don't mock the class and use the real class instead.
I am guessing that the problem you are facing is setting the RoomPreferences attribute in the roomService object. If that is the case you should add that class to the question.

Initializing repository with Spring Data JPA

image attached after answer from Lorelorelore
basically, I tried to use hibernate in my project, but it became pretty chaotic, so I decided to test it again, so I created a new spring project. I have a POJO - Car class and a CarRepository. As far as I understand, it should use basic methods from the CRUD repository - but, when I want to save a object (or use any other method) it just doesn't work (it shows that I should initialize variable "carRepository"). Could you please help me with that? Thanks in advance
//CARTESTER CLASS
public class CarTester {
public static void main(String[] args) {
#Autowired
CarRepository carRepository;
//I want to use a method from crudrepository here
carRepository.save(new Car(1, "AAA", "BBB", 1111));
carRepository.findAll();
}
}
//CAR CLASS
#Table(name = "CARS")
#Entity
public class Car {
#Id
private Integer id;
private String brand;
private String model;
private int manufactureYear;
//constructors, getters, setters, toString()
//CARREPOSITORY CLASS
#Repository
public interface CarRepository extends CrudRepository<Car, Integer> {
}
Your test class should look like this:
#RunWith(SpringRunner.class)
#DataJPATest
public class CarTester {
#Autowired
CarRepository carRepository;
#Test
public void test() {
carRepository.save(new Car(1, "AAA", "BBB", 1111));
carRepository.findAll();
}
}

Cannot instantiate mock objects using InjectMocks-Mockito

I'm new to TDD and mockito aswell, I'm trying to inject mocks into a class to perform a unit test, the class instantiate its dependencies inside a method depending on some validations, I got an error
test class/method
//Its interface
public interface UserService {
public Debt getCustomerDebt(String id);
}
//validator method
public static boolean isValidId(String id){
if(id != null && !id.isEmpty() && !id.trim().equals("")){
return true;
}
return false;
}
public class UserServiceImpl implements UserService {
private Repository repo;
private WSDLCustomerDebt wsdlCostumerDebt;
public static final int USER_EXIST = 1;
public static final int USER_DOESNOT_EXIST = 0;
public UserServiceImpl(){
}
public Debt getCustomerDebt(String id) {
if(ValidatorHelper.isValidId(id)){
repo = new RepositoryImpl();
int exist = repo.getCustomer(id);
if(exist==USER_EXIST){
wsdlCostumerDebt = new WSDLCustomerDebtImpl();
List<Date> meses = wsdlCostumerDebt.obtenerMeses(id);
if(meses.size()>0){
int totalDebt = 0;
for (Date mes : meses){
totalDebt += wsdlCostumerDebt.obtenerDeuda(mes, id);
}
return new Debt(id, BigDecimal.valueOf(totalDebt));
}else{
return new Debt(id, BigDecimal.valueOf(0));
}
}
}
return null;
}
}
mocked class repositoryimpl
public class RepositoryImpl implements Repository {
public int getCustomer(String id) {
int y = Integer.valueOf(1);
return y;
}
}
wsdl mocked class
//Interface
public interface WSDLCustomerDebt {
public List<Date> obtenerMeses(String customerId);
public Integer obtenerDeuda(Date month, String customerId);
}
public class WSDLCustomerDebtImpl implements WSDLCustomerDebt {
public List<Date> obtenerMeses(String customerId) {
return null;
}
public Integer obtenerDeuda(Date month, String customerId) {
Integer y = Integer.valueOf(11);
return y;
}
}
domain class debt
public class Debt {
private String id;
private BigDecimal debt;
public Debt(String id, BigDecimal debt) {
super();
this.id = id;
this.debt = debt;
}
//Getters and setters ....
}
finally test class
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
public class UserServiceImplTest {
#Mock
private Repository repo;
#Mock
private WSDLCustomerDebt wsdlCustomerDebt;
#InjectMocks
private UserServiceImpl userService;
#Before
public void init(){
//repo=Mockito.mock(Repository.class);
//when(wsdlcustomer.obtenerDeuda(D, customerId))
MockitoAnnotations.initMocks(this);
}
#Test
public void noExistingCustomer(){
//Given:
String id = "123";
//When:
Mockito.when(repo.getCustomer(id)).thenReturn(0);
Debt debt = userService.getCustomerDebt(id);
Mockito.verify(repo.getCustomer(Mockito.any(String.class)));
//Then:
assertNull(debt);
}
}
this is the error I'm getting and I'm trying to avoid using a constructor or any getter/setter and to receive the mocks via parameters, maybe it could be caused by a dummy error but at this point I do not know what I'm doing wrong, in fact i think the problem occurs because of the return statement in mocked classes. I'm using mockito version 1.9.5 btw
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type Integer and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
at com.i2btech.poctest.UserServiceImplTest.noExistingCustomer(UserServiceImplTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
First of all, your service doesn't use the mock you're injecting, since it creates a new one when you call the method. The repo should be an argument of the service constructor.
Second, the proper syntax to verify that a method of a mock has been called is not
verify(mock.method())
but
verify(mock).method()
(as the error message clearly says).
So, the line
Mockito.verify(repo.getCustomer(Mockito.any(String.class)))
must be replaced by
Mockito.verify(repo).getCustomer(Mockito.any(String.class))

A little guidance on jmock

I have tried the documentation on the jmock site and I'm simply lost. It appears that it's great documentation for someone that already knows how to use it. I'm not one of those. I'm looking for one of those. :)
I have a services layer that all front ends to my app communicate with. The services layer uses the DAOs to communicate with the database and return my model objects. I'd like to use Jmock for those DAOs so that there's no trips to a database.
So, I have PersonServiceImpl that implements PersonService and PersonHibernateDAO that implements PersonDAO in hibernate. Example person service follows.
public class PersonServiceImpl implements PersonService{
public void changeName(int personId, String firstName, String lastName){
person = getPersonDAO.getPerson(int personId);
person.setFirstName(firstName);
person.setLastName(lastName);
getPersonDAO.update(person);
}
}
How do I use jmock to unit test my person service?
I think this is what should work.
public class MyTestClass{
Mockery context = new Mockery();
private PersonServiceImpl personService;
private PersonDAO dao;
private Person person;
#Before
public void setup(){
person = new Person();
// set up mock to return person object
dao = context.mock(PersonDAO.class);
oneOf (dao).getPerson(5); will(returnValue(person));
// create class under test with mock
personService = new PersonServiceImpl(dao);
}
#Test
public void myTest(){
// expectations
context.checking(new Expectations() {{
oneOf (dao).update(person);
}});
// test
psersonService.changeName(....);
// verify
context.assertIsSatisfied();
}
}
Personally, I think mockito is easier...
public class MyTestClass{
private PersonServiceImpl personService;
private PersonDAO dao;
private Person person;
private ArgumentCaptor<Person> argCaptor;
#Before
public void setup(){
person = new Person();
argCaptor = ArgumentCaptor.forClass(Person.class);
// set up mock to return person object
dao = Mockito.mock(PersonDAO.class);
when(dao.getPerson(5).thenReturn(person);
// create class under test with mock
personService = new PersonServiceImpl(dao);
}
#Test
public void myTest(){
// test
psersonService.changeName(....);
// verify
verify(dao).update(argCaptor.capture());
Person passedPerson = argCaptor.getValue();
assertThat(passedPerson.getFirstName(), equalTo(...));
}
}

Categories