views:

1601

answers:

2

Hi,

I am trying to test a dao method which uses the hibernate criteria API, using JUnit4 and EasyMock 2.4.

When I run the test fixture 'testGetAsset' I receive the following exception:

java.lang.AssertionError:   
Unexpected method call add(name=Test):
   add(name=Test): expected: 1, actual: 0
   add(source=GSFP): expected: 1, actual: 0  
   uniqueResult(): expected: 1, actual: 0  
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:32)  
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:61)  
at $Proxy7.add(Unknown Source)  
at com.hsbc.sfd.funddb.persistence.dao.AssetDaoImpl.getAsset(AssetDaoImpl.java:80)  
at com.hsbc.sfd.funddb.persistence.AssetDaoTest.testGetAsset(AssetDaoTest.java:62)

I think the problem is related to the mock criteria object not being initialized with Asset.class, but I'm quite a beginner with EasyMock and mock objects in general, so I'd really appreciate it if someone could take a look and tell me what I need to do to make the test pass.

Many thanks, Mark

Code is below:

Dao Method

public Asset getAsset(String name, Source source) {
    return (Asset) this.sessionFactory.getCurrentSession()
            .createCriteria(Asset.class)
            .add(Restrictions.eq("name", name))
            .add(Restrictions.eq("source", source))
            .uniqueResult();
}

Test Class

public class AssetDaoTest {

private SessionFactory factory;
private Session session;
private Criteria criteria;

private AssetDaoImpl dao;


@Before
public void setUp() {
    factory = createMock(SessionFactory.class);
    session = createMock(Session.class);
    criteria = createMock(Criteria.class);

    dao = new AssetDaoImpl();
    dao.setSessionFactory(factory);
}

@Test
public void testGetAsset() {

    String name = "Test";
    Source source = Source.GSFP;

    Asset asset = new Asset();
    asset.setName(name);
    asset.setSource(source);

    expect(factory.getCurrentSession()).andReturn(session);
    expect(session.createCriteria(Asset.class)).andReturn(criteria);
    expect(criteria.add(Restrictions.eq("name", name))).andReturn(criteria);
    expect(criteria.add(Restrictions.eq("source", source))).andReturn(criteria);
    expect(criteria.uniqueResult()).andReturn(asset);

    replay(factory, session, criteria);

    dao.getAsset(name, source);
}
}
+2  A: 

The problem is that the Restrictions you're passing into criteria.add in the mock set up are not the exact same object instances that are passed in at the DAO level.

Take a look at EasyMock's argument matchers. You can create your own argument matchers that might give you the flexibility you're looking for, with a bit of work.

It may be worth thinking about what you're really testing here. A good way to test DAOs with hibernate is to mock your database using something like HSQL, instead of trying to mock out the hibernate criteria API. Then you can load some sample data into your in-memory database and just ensure that your DAO is behaving correctly.

Clay
A: 

Try http://code.google.com/p/hibernatemock/

CelinHC