2
votes

i'm new in Mockito and can't understand what a problem. And could you say me, how to do Mockito units correctly, because I really can't understand them! UPDATED ERROR AND TEST CLASS

I have got next exception:

java.lang.NullPointerException at ua.khpi.shapoval.autostation.service.MySqlUsersService.getUserIdByLogin(MySqlUsersService.java:49) at ua.khpi.shapoval.autostation.dao.UsersServiceTest.testGetUserByLogin(UsersServiceTest.java:57) 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:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Here is my DAO class:

  public class MySqlUsersDao implements UsersDao {
        /** Logger. */
        private static final Logger LOG = Logger.getLogger(MySqlUsersDao.class);

        /*
         * (non-Javadoc)
         * 
         * @see
         * ua.khpi.shapoval.autostation.dao.UsersDao#getUserIdByLogin(java.lang.
         * String)
         */
        @Override
        public int getUserIdByLogin(String login) {
            Connection connection = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                connection = DbConnector.getConnection();
                stmt = connection.prepareStatement(Constants.UsersDao.SELECT_USER_ID_BY_LOGIN);
                stmt.setString(1, login);
                rs = stmt.executeQuery();
                while (rs.next()) {
                    return rs.getInt(1);
                }

            } catch (SQLException e) {
                LOG.error(e.getMessage());
                return 0;
            } finally {
                DbConnector.close(connection, stmt, rs);
            }
            return 0;
        }


    }

Here is my Service class

   public class MySqlUsersService implements UsersService {

    private UsersDao usersDao;
    private TransactionManager transactionManager;

    public MySqlUsersService(UsersDao usersDao, TransactionManager transactionManager) {
        this.usersDao = usersDao;
        this.transactionManager = transactionManager;
    }

    @Override
    public int getUserIdByLogin(String login) {
        return this.transactionManager.execute(() -> this.usersDao.getUserIdByLogin(login));
    }

}

And here is my test class with Mockito

public class UsersServiceTest {
    @InjectMocks
    private MySqlUsersService mockedUsersService;

    @Mock
    private static TransactionManager transactionManager;

    @Mock
    private static UsersDao usersDao;

    @Mock
    private static Users user1;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);

    }

    @Test public void testGetUserByLogin() {
        when(usersDao.getUserByLogin("user1")).thenReturn(user1);
        assertEquals(user1, mockedUsersService.getUserIdByLogin("user1")); 
        verify(transactionManager).execute(()->usersDao.getUserIdByLogin("user1"));

    }
}
2
stackoverflow.com/questions/64636980/… Can anyone help me solve this?Rajan Shah

2 Answers

1
votes

If I understand correctly your problem in

verify(transactionManager).execute(()->usersDao.getUserByLogin("user1"));

It occurs because functions are compared by reference and the one you pass in test and the one you pass in the implementation are different instances.

I suggest you capture the function with an ArgumentCaptor. Invoke the captured function and validate it does what you expect from it.

0
votes

The error message is telling you that the verify statement was not being execute in testGetUserByLogin().

I think your actual problem is that the tested class should be annotated with @InjectMocks in your test class. This annotation tells Mockito which class to inject mocks into:

@InjectMocks
private MySqlUsersService mockedUsersService

I would rewrite your test this way:

public class UsersServiceTest { 

@InjectMocks
private MySqlUsersService mockedUsersService;

@Mock 
private static TransactionManager transactionManager;

@Mock
 private static UsersDao usersDao;

@Mock 
private static Users user1;

@Before 
public static void init() { initMocks(this); }

@Test public void testGetUserByLogin() {
    when(usersDao.getUserByLogin("user1")).thenReturn(user1);
    assertEquals(user1, mockedUsersService.getUserIdByLogin("user1")); 
    verify(transactionManager).execute(()->usersDao.getUserIdByLogin("user1"));

} }