0

This is the (simplified) method that I need to write a unit test case in mockito, however I get a null pointer exception:

public class Class1 {
    @Autowire
    AutoWiredObject autoWiredObject;

    public Object1 getAccount(boolean b1) {
       Object1 object = new Object1();
       autoWiredObject.setAllValues(object); //object.get("value") is set to something
                                            //here. Also this is where the exception follows when I test the unit test method
       return object;
    }
}

I tried something like this in the test class:

@InjectMocks 
Class1 myClass;

@Spy // I researched this is how we solve the issue of autowired
AutoWiredObject autoWiredObject = new AutoWiredObject();

@Test
public void testGetAccount() {
   Object1 object = myClass.getAccount(true); //this is where the null pointer exception
                                               //starts
   assertTrue(object.get("value") != null);
}

What is the best way to unit test this type of methods? by the way, if I check the implementation of the AutowiredObject class, the "setAllValues" methods also contains an autowired object inside calling a method, so my point is, how to deal with this "chain" of autowired??

Or is there another easier way for me to test the line

autowiredObject.setAllValues(object) 

??

mchl45
  • 29
  • 6

1 Answers1

0

If you can't change the Class1 implementation I think that instantianting the spy should solve the problem:

@Spy
AutoWiredObject autoWiredObject = new AutoWiredObject(/*parameters*/);

There is a nice explanation here about mocks vs. spies.

Now, if you could change the Class1...

I have a personal preference to write and test my services regardless the injection framework used. Usign your Class1 as an example, I would rewrite it using a constructor injector:

public class Class1 {        
    private final AutoWiredObject autoWiredObject;

    @Autowire
    public Class1(AutoWiredObject autoWiredObject) {
        this.autoWiredObject = autoWiredObject;
    } 

    public Object1 getAccount(boolean b1) {
       Object1 object = new Object1();
       autoWiredObject.setAllValues(object);

       return object;
    }
}

Now i don't need @InjectMocks or @Spy during the tests, just good old Mockito syntax:

void testAccount() {
    //arrange
    AutoWiredObject autoWiredSpy = Mockito.spy(new AutoWiredObject(/*parameters*/));
    Class1 myClass = new class1(autoWiredSpy);
    //act
    Object1 result = myClass.getAccount(true);
    //assert
    assertNotNull(result.get("value"));
} 

I am supposing AutoWiredObject has a default constructor. Also check your parameter b1 as it seems you are not using it.

marcellorvalle
  • 1,631
  • 3
  • 17
  • 30
  • thanks for your answer, but I am not allowed to modify Class1, as you are suggesting, so I have to write the unit test with Class1 as it originally is – mchl45 Oct 27 '21 at 02:11
  • Oh... this is bad. Maybe you can instantiate the spy object: AutoWiredObject autoWiredObject = new autoWiredObject(); I will edit my answer. – marcellorvalle Oct 27 '21 at 02:14
  • @mchl45 suggest to your team that refactoring to improve testability is time well spent. – tgdavies Oct 27 '21 at 03:50