简体   繁体   中英

object mocking is not working (its null) and returns NullPointerException on method call

Here is my class A under test -

class A extends ServerResource {
    @Override
    protected void doInit() throws ResourceException {
    }

    @Get
    public String getUsers() {
        String userJson = null;
        // want to mock 
        UserFacade userFacade = new UserFacade();
        // database call: want to return resources
        List<Resource> resources = userFacade.getDrUsersByExample();
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        userJson = gson.toJson(resources);
        return userJson ;
    }

}

Here is test class -

@RunWith(MockitoJUnitRunner.class)
class ATest {
    @Mock
    UserFacade userFacade;

    List<Resource> resources;

    @Before
    public void setUp() throws Exception {
      Resource resource = new Resource();
      resource.setName("user");
      resource.setTask("manual");
      resources.add(resource);
    }

    @Test
    public void testUsers() {
      when(userFacade.getDrUsersByExample()).thenReturn(resources);

      A a = new A();

      // causes NullPointerException for userFacade.getDrUsersByExample()
      String userList = a.getUsers();
    }

}

Why I am getting NullPointerException for the mocked object even after using when(userFacade.getDrUsersByExample()).thenReturn(resources) ?

Mocked UserFacade needs to be explicitly injected into subject under test. A is currently tightly coupled to that dependency because of new UserFacade() inside the method.

Tight coupling is considered a code smell and poor design. Refactor the class to follow explicit dependency principle.

class A extends ServerResource {
    UserFacade userFacade;

    public A(UserFacade userFacade) {
        this.userFacade = userFacade;
    }

    @Override
    protected void doInit() throws ResourceException {
    }

    @Get
    public String getUsers() {
        String userJson = null;
        // database call: want to return resources
        List<Resource> resources = userFacade.getDrUsersByExample();
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        userJson = gson.toJson(resources);
        return userJson ;
    }
}

Test would then need to be updated in order to be exercised to completion.

@Test
public void testUsers() {
    //Arrange
    when(userFacade.getDrUsersByExample()).thenReturn(resources);

    A a = new A(userFacade);

    //Act
    String userList = a.getUsers();

    //Assert
    //...
}

By getting tips from @Nkosi that we somehow need to pass mock object into the class under test, I got things work for me-

class A extends ServerResource {
    UserFacade userFacade;

    @Override
    protected void doInit() throws ResourceException {
      this.userFacade = userFacade;
    }

    @Get
    public String getUsers() {
        String userJson = null;
        // database call: want to return resources
        List<Resource> resources = userFacade.getDrUsersByExample();
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        userJson = gson.toJson(resources);
        return userJson ;
    }

    public void setUserFacade(UserFacade userFacade) {
        this.userFacade= userFacade;
    }
}

Then the test class -

@Test
public void testUsers() {
    //Arrange
    when(userFacade.getDrUsersByExample()).thenReturn(resources);

    A a = new A();
    a.setUserFacade(userFacade);

    //Act
    String userList = a.getUsers();

    //Assert
    //...
}

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