I have been trying to run the following test using mockito and junit and I keep on getting "java.lang.NullPointerException: name must not be null"
Can anyone tell me why this is happening?
On debugging, I found out that this exception is thrown when the test executes the following statement in isStopValid(String) method:
FacilityValidationUtil facUtil = new FacilityValidationUtil();
#RunWith(MockitoJUnitRunner.class)
public class MyFormTest{
#InjectMocks MyForm form = new MyForm();
#Mock FacilityValidationUtil facUtil;
#Test
public void testIsStopValid() throws FinderException{
when(facUtil.isFacilityValid("")).thenReturn(false);
form.setOrigin("");
assertEquals(false, form.isStopValid(form.getOrigin()));
}
}
Class with method to be tested:
public class MyForm{
FacilityValidationUtil facUtil = new FacilityValidationUtil();
public boolean isStopValid(String stop){
try {
return facUtil.isFacilityValid(stop);
} catch (FinderException e) {
log.error("Error finding the stop. "+e.getCause());
return false;
}
}
}
public class FacilityValidationUtil{
private FacilityDAO facilityDao = new HibernateFacilityDAO();
public boolean isFacilityValid(String facility) throws FinderException{
boolean test;
FacilityImpl facilityImpl = facilityDao.findFacilityByNassCode(facility);
test = (facilityImpl==null)?false : true;
return test;
}
}
public class HibernateFacilityDAO extends HibernateAbstractDeltaDAO implements FacilityDAO {
public HibernateFacilityDAO() {
super(false);
}
}
Short Answer: You are trying to mock a variable (facUtil) that is local to your isStopValid method, so the mock version of this object in your test is never going to be called because you are 'newing it up" each time.
Long Answer: It looks like you are trying to mock the call to your FacilityValidationUtil class, and if this is the case, then you need to either make the class a field so that Mockito can inject the object by reflection (if this object is thread safe, which it looks like it is) or explore a mocking framework like PowerMockito that will allow you to mock a constructor (google for PowerMockito when new).
PowerMockito.whenNew(FacilityValidationUtil.class).withNoArguments().thenReturn(facUtil);
Mockito doesn't support any mocking of constructor args by default.
EDIT
If you are still having trouble, then I would suggest starting with a smaller example. I've put together one for you that works and uses the code you are trying to test (It's using inner classes though, which Mockito has some quirky rules about, but I'm just doing it to compress the example).
#RunWith(MockitoJUnitRunner.class)
public class MyFormTest {
#InjectMocks
private MyForm form = new MyForm();
#Mock
private FacilityValidationUtil facUtil;
#Test
public void testIsStopValid_false() {
when(facUtil.isFacilityValid("")).thenReturn(false);
assertEquals(false, form.isStopValid(""));
}
#Test
public void testIsStopValid_true() {
when(facUtil.isFacilityValid("")).thenReturn(true);
assertEquals(true, form.isStopValid(""));
}
public class MyForm {
private FacilityValidationUtil facUtil = new FacilityValidationUtil();
public boolean isStopValid(String stop) {
try {
return facUtil.isFacilityValid(stop);
} catch (FinderException e) {
return false;
}
}
}
public class FacilityValidationUtil {
public boolean isFacilityValid(String facility) throws FinderException {
throw new RuntimeException(facility);
}
}
public class FinderException extends RuntimeException {
public FinderException(String message) {
super(message);
}
}
}
What's really important is that your mock is not getting injected correctly. Until you get that resolved, you are going to keep getting the same error. Set a break point in your MyForm at the point you call facUtil.isFaciltyValid and look at the object. It should be a mockito object, not your class.
Good luck.
Related
I have Utils class with method which throws exception when given data are incorrect.
I have also Service which uses this method, but the data are always generated in way that they will be correct during call. Data are generated by another utils class.
I understand that I should throw this exception from Utils class - but I can't throw it from Service - so I have to catch it.
How can I test this, simulate this exception?
All actions on this data are in private methods.
I want to avoid PowerMock, because I heard that it's a sign of bad design.
So the question is, how to implement this in good design?
From your description it looks like this:
class Service {
public void someMethod() {
Data data = AnotherUtils.getData();
try {
Utils.method(data); // exception never thrown
} catch(Exception e) {
// how to test this branch?
}
}
}
The goal would be something like this:
interface DataProvider {
Data getData();
}
interface DataConsumer {
void method(Data data);
}
class Service {
private final DataProvider dataProvider;
private final DataConsumer dataConsumer;
public Service(DataProvider dataProvider, DataConsumer dataConsumer) {...}
public void someMethod() {
Data d = dataProvider.getData();
try {
dataConsumer.method(data);
} catch(Exception e) {
}
}
}
This technique is called dependency injection.
Then, when testing, you can simply provide a mock implementation for this DataProvider interface that does return faulty data:
#Test(expected=Exception.class)
public void myTest() {
DataProvider badDataProvider = () -> new BadData(); // Returns faulty data
Service service = new Service(badDataProvider, Utils.getConsumer());
service.someMethod(); // boom!
}
For the non-testing code, you could simply wrap the utils classes you already have in these interfaces:
class AnotherUtils {
public static Data getData() {...}
public static DataProvider getProvider() {
return AnotherUtils::getData;
}
}
...
Service service = new Service(AnotherUtils.getProvider(), Utils.getConsumer());
Here is an approach where you want to introduce Dependency Injection, but for whatever reason you don't want to change legacy code.
Say you have some static utility method like so:
class Utils{
public static Something aMethod(SomethingElse input) throws AnException{
if(input.isValid())
return input.toSomething();
throw new AnException("yadda yadda");
}
}
And you have a class that uses that utility method. You can still inject it with a FunctionalInterface.
#FunctionalInterface
interface FunctionThrowsAnException<K,V> {
V apply(K input) throws AnException;
}
class Service {
private final FunctionThrowsAnException<SomethingElse,Something> func;
Service(FunctionThrowsAnException<SomethingElse,Something> func){
this.func = func;
}
Something aMethod(SomethingElse input){
try{
return func.apply(input);
}catch(AnException ex){
LOGGER.error(ex);
}
}
}
Then use it like this:
new Service(Utils::aMethod).aMethod(input);
To test it:
new Service(x -> { throw new AnException("HA HA"); }).aMethod(input);
i wanted to write some tests for the method shown in the code below. I'm mocking dependencies with JMockit. For whatever reason i am getting a NullPointerException all the time and i really don't understand why that happens. I'm new to JMockit and in mocking dependencies in general. Stack Trace just shows NullPointerException thrown at line new NonStrictExpectations()
.
Method to test:
#Override
public boolean addSubject(User user, Schedule schedule, SchoolSubject subject) {
final boolean result = schedule.addSubject(subject.getHourTime(), subject);
scheduleDAO.update(schedule);
if (subject.getTeacher() != null && !subject.getTeacher().trim().isEmpty()) {
for (final TeacherEntry teacher : user.getTeachers()) {
if (subject.getTeacher().equals(teacher.getName())) {
teacher.getSubjects().add(subject.getName());
teacherDAO.update(teacher);
}
}
}
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
}
Test method:
//imports not copied
public class ScheduleManagerTest {
#Tested
ScheduleManager manager;
#Injectable
UserDAO userDAO;
#Injectable
ScheduleDAO scheduleDAO;
#Injectable
TeacherEntryDAO teacherDAO;
#Injectable
SchoolSubjectDAO schoolSubjectDAO;
#Mocked
Schedule schedule;
#Mocked
SchoolSubject subject;
#Mocked
User user;
#Test
public void testAddSubject() throws DuplicateUsernameException, DuplicateEmailException {
new NonStrictExpectations() {
{
schedule.addSubject(anyInt, (SchoolSubject) any);
result = true;
scheduleDAO.update((Schedule) any);
subject.getTeacher();
result = anyString;
subject.getTeacher().trim().isEmpty();
result = false;
user.getTeachers();
result = (ArrayList<TeacherEntry>) any;
teacherDAO.update(((TeacherEntry) any));
userDAO.update((User) any);
};
};
assertTrue(manager.addSubject(user, schedule, subject));
}
}
I think i'm doing something pretty wrong :(
It's hard to know what is going wrong based on the description, but here's a guess:
Mocked objects will return null in their methods by default. You'll get a null pointer here:
subject.getTeacher().trim()
because getTeacher() will return null. To return a teacher, you'll have to either use a real subject or do further mocking with
Mockito.when(subject.getTeacher()).thenReturn(new Teacher());
You need to add #RunWith(JMockit.class) to your class
#RunWith(JMockit.class)
public class ScheduleManagerTest {
...
I have a class which I would like to test with a public static method that contains some chained method calls. Assuming that an exception occurs during the chained method calls, how do I handle this effectively and make it return some specific value?
Following is the code sample of the test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class,CodeWithYetAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = PowerMockito.spy(new CodeWithYetAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithYetAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithYetAnotherPrivateMethod);
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
PowerMockito.doReturn(true).when(codeWithYetAnotherPrivateMethod, "getGambling");
//PowerMockito.doReturn(codeWithYetAnotherPrivateMethod).when(codeWithAnotherPrivateMethod, "getGambleValue");
PowerMockito.spy(CodeWithPrivateMethod.class);
CodeWithPrivateMethod.startGamble();
}
}
Following is the code sample for the class under test
public class CodeWithPrivateMethod {
public static void startGamble() {
Boolean gamble = CodeWithAnotherPrivateMethod.getGambleValue()
.getGambling();
if (gamble) {
System.out.println("kaboom");
}else{
System.out.println("boom boom");
}
}
}
Following is the code sample for the class that gets called from the class under test
public class CodeWithAnotherPrivateMethod {
static CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = new CodeWithYetAnotherPrivateMethod();
public static CodeWithYetAnotherPrivateMethod getGambleValue() {
return codeWithYetAnotherPrivateMethod; //works fine
return null; // fails
}
}
Following is the code sample for the other class that gets called from the class under test
public class CodeWithYetAnotherPrivateMethod {
public Boolean getGambling() {
return false;
}
}
So Assuming I return a null value from getGambleValue() method of CodeWithAnotherPrivateMethod class, how do I handle this null value effectively in my testclass?
This is how to specify expected exceptions using Mockito:
#Test(expected = NullPointerException.class)
public void when_gambling_is_true_then_always_explode() throws Exception {
...
Before I found out about this I would do:
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
// setup omitted
try {
CodeWithPrivateMethod.startGamble();
}
catch(NullPointerException e) {
// expected
return;
}
fail("Expected NullPointerException");
}
EDIT: Testing multiple classes that call each other statically like this is a severe code smell. Unit tests should test a single class and inline static calls should be limited to utility classes.
Another comment: your example class names are very confusing. Next time please stick with Foo, Bar, Baz or Appple, Pear, Banana.
If you are not getting an NPE then I expect your mocking/spying is interfering. If you call the code under test without mocking/spying the call chain would be:
CodeWithPrivateMethod.startGamble();
->
CodeWithYetAnotherPrivateMethod value = CodeWithAnotherPrivateMethod.getGambleValue();
->
return null;
<-
value.getGambling();
<- throws NullPointerException
What exactly are you trying to find out or achieve?
EDIT: Here's how it should work with PowerMock
#RunWith(PowerMockRunner.class)
#PrepareForTest(CodeWithAnotherPrivateMethod.class)
public class CodeWithPrivateMethodTest {
#Mock
private CodeWithYetAnotherPrivateMethod yetAnotherInstance;
#Test
public final void testStartGamble() {
// SETUP
mockStatic(CodeWithAnotherPrivateMethod.class);
expect(CodeWithAnotherPrivateMethod.getGambleValue())
.andReturn(yetAnotherInstance);
Boolean gamblingValue = true;
expect(yetAnotherInstance.getGambling()).andReturn(gamblingValue);
replayAll();
// CALL
CodeWithPrivateMethod.startGamble();
// VERIFY
verifyAll();
}
I have a problem when writing unit testing with mock. There is a object which I need to mock have a lot getter, which I do call them at the code. However, those are not the purpose of my unit test. So, is there is a way I can mock all the methods instead of mock them one by one.
Here is the code example:
public class ObjectNeedToMock{
private String field1;
...
private String field20;
private int theImportantInt;
public String getField1(){return this.field1;}
...
public String getField20(){return this.field20;}
public int getTheImportantInt(){return this.theImportantInt;}
}
and this is the service class I need to test
public class Service{
public void methodNeedToTest(ObjectNeedToMock objectNeedToMock){
String stringThatIdontCare1 = objectNeedToMock.getField1();
...
String stringThatIdontCare20 = objectNeedToMock.getField20();
// do something with the field1 to field20
int veryImportantInt = objectNeedToMock.getTheImportantInt();
// do something with the veryImportantInt
}
}
within the test class, the test method is like
#Test
public void testMethodNeedToTest() throws Exception {
ObjectNeedToMock o = mock(ObjectNeedToMock.class);
when(o.getField1()).thenReturn(anyString());
....
when(o.getField20()).thenReturn(anyString());
when(o.getTheImportantInt()).thenReturn("1"); //This "1" is the only thing I care
}
So, is there a way that I can avoid writing all the "when" for the useless "field1" to "field20"
You can control the default answers of your mock. When you're creating the mock, use:
Mockito.mock(ObjectNeedToMock.class, new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
/*
Put your default answer logic here.
It should be based on type of arguments you consume and the type of arguments you return.
i.e.
*/
if (String.class.equals(invocation.getMethod().getReturnType())) {
return "This is my default answer for all methods that returns string";
} else {
return RETURNS_DEFAULTS.answer(invocation);
}
}
}));
If you're not interested in the result of getField1() to getField20() in a particular test case, you shouldn't mock it at all. In other words, if all the specific test case should be concerned about is getTheImportantInt(), then your test case should look like this:
#Test
public void testMethodNeedToTest() throws Exception {
ObjectNeedToMock o = mock(ObjectNeedToMock.class);
when(o.getTheImportantInt()).thenReturn("1");
// test code goes here
}
For kotlin users:
val mocked:MyClassToMock = Mockito.mock(MyClassToMock::class.java,
object:Answer<Any> {
override fun answer(invocation: InvocationOnMock?): Any {
if (String::class.java.equals (invocation?.method?.getReturnType())) {
return "Default answer for all methods that returns string";
} else {
return Mockito.RETURNS_DEFAULTS.answer(invocation);
}
}
})
I think I might have found a bug in JMockit, but I would like some to confirm whether it's a bug or there's something I'm missing.
I have the following (very simple) class:
public class Dummy {
public void foo() {System.out.println("O");}
}
Now I have the following tests, where in each of them I try to mock the method 'foo' more than once (each test does it a little differently):
Test #1
#Test
public void test1() {
new MockUp<Dummy>() {
#Mock
public void foo(Invocation inv) {
System.out.println("A");
inv.proceed();
}
}
new MockUp<Dummy>() {
#Mock
public void foo(Invocation inv) {
System.out.println("B");
inv.proceed();
}
}
new Dummy().foo();
}
Test #2
#Test
public void test2() {
mock("A");
mock("B");
new Dummy().foo();
}
private void mock(final String s) {
new MockUp<Dummy>() {
#Mock
public void foo(Invocation inv) {
System.out.println(s);
inv.proceed();
}
}
}
The only difference between the tests is the extraction of the mock code to a different method. But the results are not the same...
Test #1 output:
B
A
B
O
This is odd, because I wouldn't expect A to appear at all. But anyway, here's test #2 output:
B
A
A
A
...ad infinitum
Test #2 will fail with a StackOverflowError.
Is this a bug or am I missing something?
Update (with the solution)
As #Rogério mentioned, this behavior is not acceptable.
Then how can the mock be overridden? like this:
private MockUp<Dummy> mock;
#Test
public void test3() {
mockCorrectly("A");
mockCorrectly("B");
new Dummy().foo();
}
private void mockCorrectly(final String s) {
if (mock != null) {
mock.tearDown();
}
mock = new MockUp<Dummy> {
#Mock
public void foo(Invocation inv) {
System.out.println(s);
inv.proceed();
}
}
}
And for the output:
B
O
Great :)
It's not clear what exactly happens here; apparently, at runtime some "chained mocking" is occurring.
The real problem is that both tests are doing something invalid with the MockUp API: they are mocking the same method in the same class twice in the same test. It is ok to have two different mock-ups for the same class in the same test, as long as they mock different methods/constructors.
The resulting behavior is undefined, as JMockit does not support multiple simultaneous mockings of the same method.