Search code examples
javaunit-testingjunitmockingjmockit

How Do I mock a DAO Layer using JMockit?


I am trying to mock a DAO layer Interface which looks something like this ...

      public interface DummyDAO{

     public List<VO> getSearchCriteria(String Id, Integer version) throws Exception;

      }

In the implementation part, I run a query, and it fetches me a list of Value objects based on that query. How do I mock a List of VO's coming from a database. Is there a simple way to do this ?. I am trying to encourage my team to use Jmockit but I am still a newbie to this mocking tool. If you need more info please let me know.

Thanks


Solution

  • The answer here can depend partly on how the CUT (code under test) is using the List<VO>. For example, if your code is a RESTful service merely acting as a proxy and returning this List<VO> to the user, without examining the contents or anything, then this would suffice:

    @Tested CUT cut;
    @Injectable DummyDAO dao;
    @Injectable List<VO> res;
    
    @Test
    public void testSomething() throws Exception {
        new Expectations() {{
            dao.getSearchCriteria(anyString, anyInt); result = res; 
        }};
        List<VO> output = cut.methodBeingTested();
        // assertions go here, like that output and res are the same
        // you can also put Verifications here
    }
    

    If you are expecting to do analysis of the VOs then things can get more complex, like for example:

    @Tested CUT cut;
    @Injectable DummyDAO dao;
    @Mocked VO vo;
    
    @Test
    public void testSomething() throws Exception {
        final List<VO> res = new ArrayList<VO>();
        Collections.addAll(res, vo, vo, vo, vo);
        new Expectations() {{
            dao.getSearchCriteria(anyString, anyInt); result = res;
        }};
    
        new Expectations(4) {{
            vo.getFoo(); returns(5, 47, 13, -7);
        }};
    
        cut.methodBeingTested();
        // assertions go here, like that you handled the negative number properly
        // you can also put Verifications here
    }
    

    Notice here I did not mock the List -- if you are doing more complex operations it's better to stick with a real List and not have to mock all of its operations. I mock a single VO and add it to the list multiple times--this is OK because each time you examine it it will act differently and thus seem to be a different VO.

    The examination, because it is happening 4 times, I moved to a different Expectations block since you are expecting it to happen 4 times. I'm just doing this to show off the expectations block since in this case it could be just as easily accomplished by having vo.getFoobar(); times=4; returns(5, 47, 13, -7); in the original block... alternatively, this second block could look like

        new StrictExpectations(4) {{
            vo.getFoo(); returns(5, 47, 13, -7);
            vo.getBar(); returns("foo", "bar", "baz", "quux");
        }};
    

    In this case, the times field would not work and you'd have to have it in a separate block - this block is saying it expects to have getFoo() and getBar() called, alternating, exactly 4 times--as you would want to do if iterating through a list and looking at both properties each time.

    I hope I have given you food for thought; without knowing more of your specific use case I can't be more specific myself.