[mockito] Problems mocking hibernate classes

2,017 views
Skip to first unread message

CésarO

unread,
Apr 23, 2010, 6:27:19 PM4/23/10
to mockito
Hi everyone!

I'm very new to using mockito, and I'm having a hard time figuring out
how to mock hibernate classes so I can test GWT services. This is the
method I want to test:

public ExpertiseArea saveExpertiseArea(ExpertiseArea ea) {
try{
expertiseAreaValidator.assertValid(ea);
}catch(InvalidStateException ise){
invalidValues = expertiseAreaValidator.getInvalidValues(ea);
}

try{
dao.setSession(getSessionFactory().getCurrentSession());
dao.getSession().beginTransaction();
ExpertiseArea result = dao.makePersistent(ea);
return result;
}catch(HibernateException he){
Log.debug(he.getMessage());
}finally{
dao.getSession().getTransaction().commit();
}
return null;
}

I don't want the test to depend on the dao, so I'm trying to mock out
the dependencies:

public void setUp(){
service = (AOEServiceImpl)appContext.getBean("AOEServiceImpl");
serviceSpy = spy(service);

ExpertiseAreaDAO dao = service.getDao();
SessionFactory sessionFactory = mock(SessionFactory.class);
Session session = mock(Session.class);

when(sessionFactory.getCurrentSession()).thenReturn(session);
stub(serviceSpy.getSessionFactory()).toReturn(sessionFactory);
}

I'm using a spy here to return a mocked SessionFactory. Then the
actual test:

public void testEntityIsValidatedCorrectly(){
ExpertiseArea ea = new ExpertiseArea("TestArea");
assertNotNull("Entity should not be null", ea);
ea = serviceSpy.saveExpertiseArea(ea);
assertNotNull("Entity should not be null", ea);

ea = new ExpertiseArea();
ea.setName(null);
assertNull("Entity should not validate",
service.saveExpertiseArea(ea));
}

The problem is that, when I call serviceSpy.saveExpertiseArea() and
that in turn calls it's getSessionFactory(), the real
getSessionFactory() is called, throwing a NullPointerException instead
of returning the mocked sessionFactory.

The getSessionFactory() method is inherited from a base class, called
BaseServiceImpl, maybe that's important.

Any suggestion is greatly appreciated. Thanks in advance!

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To post to this group, send email to moc...@googlegroups.com.
To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mockito?hl=en.

szczepiq

unread,
Apr 24, 2010, 6:44:32 AM4/24/10
to moc...@googlegroups.com
Hey,

I wouldn't mock 3rd party libs like hibernate. Here's how the code might look like - easy to test:


public ExpertiseArea saveExpertiseArea(ExpertiseArea ea) {
               try {
                       expertiseAreaValidator.assertValid(ea);
               } catch(InvalidStateException ise) {
                       invalidValues = expertiseAreaValidator.getInvalidValues(ea);
               }

                  return persistor.persist(etenta);
       }

If the code is hard to test refactor it so that it is easy to test. If you don't know how to test your code & have to ask questions on mailing lists - ods are 97% that your code simply needs to be refactored. Good luck!

Not sure why you're facing problem of real implementation executed instead of stubbed. Typically it is related to stubbing final methods or calling stubbed methods with wrong args.

Cheers,
Szczepan

On Sat, Apr 24, 2010 at 12:27 AM, CésarO <cesa...@gmail.com> wrote:
Hi everyone!

I'm very new to using mockito, and I'm having a hard time figuring out
how to mock hibernate classes so I can test GWT services. This is the
method I want to test:

       public ExpertiseArea saveExpertiseArea(ExpertiseArea ea) {
               try{
                       expertiseAreaValidator.assertValid(ea);
               }catch(InvalidStateException ise){
                       invalidValues = expertiseAreaValidator.getInvalidValues(ea);
               }

               try{
                       dao.setSession(getSessionFactory().getCurrentSession());
                       dao.getSession().beginTransaction();
                       ExpertiseArea result = dao.makePersis(etenta);

James Carr

unread,
Apr 24, 2010, 9:26:57 AM4/24/10
to moc...@googlegroups.com
Yep... the rule is don't mock objects you don't own... it's a recipe
for disaster. :)

Graham Allan

unread,
Apr 24, 2010, 10:01:30 AM4/24/10
to moc...@googlegroups.com
>Yep... the rule is don't mock objects you don't own... it's a recipe
>for disaster. :)

Hi James,

I've never considered this before and I'm interested in finding out more. Have
you got a source explaining this, so I can read up on the justification of it?

Kind regards,
Graham

James Carr

unread,
Apr 24, 2010, 11:58:50 AM4/24/10
to moc...@googlegroups.com
There's lots of sources, however Steve Freeman mentions it a bit
(along with a lot of other good practices) in the book Growing Object
Oriented Software Guided By Tests.

Personally, I tend to not mock objects I don't own because that
integration point can often be brittle and I also further consider it
bad design to expose that thried party API into my domain. I often
test drive an integration test against an adapter or wrapper that
wraps the library to make sense within my domain, then mock that role
out. In the hibernate example, I'd test drive a dao using hibernate
with a fake database (say H2 or hsql)... then I'll be free to mock the
dao out in my other tests.

Hope that Helps,
James

CésarO

unread,
Apr 24, 2010, 12:11:23 PM4/24/10
to mockito
Thanks for the suggestion. I'll give it a go and post my results when
I get home.
> > mockito+u...@googlegroups.com<mockito%2Bunsu...@googlegroups.com >
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/mockito?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "mockito" group.
> To post to this group, send email to moc...@googlegroups.com.
> To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/mockito?hl=en.

CésarO

unread,
Apr 24, 2010, 12:17:10 PM4/24/10
to mockito
That's exactly what I was going for. I do have a dao wrapping
hibernate, and I do have integration tests with an in-memory HSQLDB.
Things went wrong when I tried to mock the dao, and that led me to
mock the SessionFactory, and that led me to mock the Session, and the
Transaction, etc.
> > For more options, visit this group athttp://groups.google.com/group/mockito?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "mockito" group.
> To post to this group, send email to moc...@googlegroups.com.
> To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/mockito?hl=en.

Graham Allan

unread,
Apr 24, 2010, 12:25:11 PM4/24/10
to moc...@googlegroups.com
>There's lots of sources, however Steve Freeman mentions it a bit
>(along with a lot of other good practices) in the book Growing Object
>Oriented Software Guided By Tests.
>
>Personally, I tend to not mock objects I don't own because that
>integration point can often be brittle and I also further consider it
>bad design to expose that thried party API into my domain. I often
>test drive an integration test against an adapter or wrapper that
>wraps the library to make sense within my domain, then mock that role
>out. In the hibernate example, I'd test drive a dao using hibernate
>with a fake database (say H2 or hsql)... then I'll be free to mock the
>dao out in my other tests.
>
>Hope that Helps,
>James

It seems to me, in my (blatant lack of) experience that this is a choice that
will be dependent on the context, rather than a hard-and-fast rule. I'd expect
cases where creating the wrapper would be overkill, and mocking the third-
party code wouldn't be an issue.

But since I don't want to take the mailing list off-topic, I'll just say thank
you for the reference and carry on with my reading :-)

Cheers James,
Reply all
Reply to author
Forward
0 new messages