Search code examples
javajmockit

JMockit | trying to define different return values based on parameters but getting unexpected results


I've got a class like the following:

class A
{
   public method doSomething()
   {
      //....

      DAO dataAccessor = new DAO();
      List<Object> result1 = dataAccessor.getData(dataAccessor.getSql1());
      List<Object> result2 = dataAccessor.getData(dataAccessor.getSql2());

      //.. do some stuff with the results

}

Now, I use jMockit for testing the above function, by mocking the DAO class.

This is how my test class looks like:

class A_Test
{
    private A myAClass;

    @Mocked DAO mockedDAO;

    List<Object> resultToSql1, resultToSql2;

    // ... Some initializations...

    @Test
    public void testDoSomething()
    {
        new NonStrictExpectations()
        {
                mockedDAO.getSql1(); result = "SQL1";
                mockedDAO.getData(withEqual("SQL1")); result = resultToSql1;

                mockedDAO.getSql2(); result = "SQL2";
                mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
        };

        myAClass.doSomething(); 
    }
}

Now, it seems that the second expectation regarding getData() masks the first one, i.e. the mock object behaves as if I never declared the first lines in the expectation (the ones that handle sql1):

The first call to getData() returns empty collection, instead of the values with which I initialized resultToSql1. The second call returns resultToSql2, as expected.

If I comment the following line:

mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;

the first call is returning what I defined - resultToSql1, and the second returns empty collection. This makes sense.

So, what am I doing wrong? ?How can I define two different return values from getData() based on the parameters of the call?

Any help would be appreciated.

Thanks!


Solution

  • So, After digging more deeply inside the manual, I found that:

    ...But what if a test needs to decide the result of a recorded invocation based on the arguments it will receive at replay time? We can do it through a mockit.Delegate instance ...

    So, in order to solve the above problem, the expectations block should look like this:

        new NonStrictExpectations()
        {
                mockedDAO.getSql1(); result = "SQL1";
                mockedDAO.getSql2(); result = "SQL2";
    
                mockedDAO.getData(anyString);
                result = new mockit.Delegate()
                {
                    List<Object> getData(String sql)
                    {
                        if (sql.equals("SQL1"))
                            return resultToSql1;
                        if (sql.equals("SQL2"))
                            return resultToSql2;
                        return null;
                    }
                }
        };