Help Needed with mocking factory

2,255 views
Skip to first unread message

Rahul

unread,
Jan 5, 2010, 5:20:31 PM1/5/10
to mockito
Hi All,

Am new to mockito and am stuck with a situation where I have to test
some code which uses factories.

The method to test is something like this :

public Integer save(session, dto) {
PersistenceManagerFactory persistMgrFactory =
PersistenceManagerFactory .getInstance();
PersistenceManager aPersistanceMgr =
persistMgrFactory.getPersistenceManager(A.class) ;
aPersistanceMgr.load(session, dto.getInt() ) ; // I want to stub this
method which am unable to do
}

I can pass mock session and dto and stub methods on them, but am not
able to mock the aPersistanceMgr or stub the methods on it.

Any pointer/pseudo code would be much appreciated.

Thanks,
Rahul

Kartik Kumar

unread,
Jan 5, 2010, 8:14:32 PM1/5/10
to moc...@googlegroups.com
I don't think that static code can be mocked by Mockito. You probably have to do it at byte code level. PowerMock can do it for you. Perhaps this may help

http://code.google.com/p/powermock/wiki/MockitoUsage13

--
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.




Michael Hackett

unread,
Jan 5, 2010, 8:27:08 PM1/5/10
to moc...@googlegroups.com
Rahul,

You can't mock global objects (like the Singleton PersistenceManagerFactory), unless you can replace the instance it returns. Instead, you should pass the factory into the save method, or the constructor of the class the method belongs to. Then you can create a mock PersistenceManagerFactory and pass it in.

Your test code might look something like this:

   PersistenceManagerFactory mockFactory = mock(PersistenceManagerFactory.class);
   PersistenceManager mockManager = mock(PersistenceManager.class);
   when(mockManager).load(...) ...
   when(mockFactory).getPersistenceManager(any(A.class)).thenReturn(mockManager);

   xxx.save(mockFactory, session, dto);

   verify(...);

Cheers,
-- Michael

2010/1/5 Rahul <rah...@gmail.com>

Rahul

unread,
Jan 5, 2010, 10:02:45 PM1/5/10
to mockito
Thanks Kartik. Let me have a look if this would solve my problem

On Jan 5, 7:14 pm, Kartik Kumar <krishnan.1...@gmail.com> wrote:
> I don't think that static code can be mocked by Mockito. You probably have
> to do it at byte code level. PowerMock can do it for you. Perhaps this may
> help
>
> http://code.google.com/p/powermock/wiki/MockitoUsage13
>

> On Tue, Jan 5, 2010 at 2:20 PM, Rahul <rahu...@gmail.com> wrote:
> > Hi All,
>
> > Am new to mockito and am stuck with a situation where I have to test
> > some code which uses factories.
>
> > The method to test is something like this :
>
> > public Integer save(session, dto) {
> >  PersistenceManagerFactory persistMgrFactory =
> > PersistenceManagerFactory .getInstance();
> >  PersistenceManager aPersistanceMgr =
> > persistMgrFactory.getPersistenceManager(A.class) ;
> >  aPersistanceMgr.load(session, dto.getInt() ) ; // I want to stub this
> > method which am unable to do
> > }
>
> > I can pass mock session and dto and stub methods on them, but am not
> > able to mock the aPersistanceMgr or stub the methods on it.
>
> > Any pointer/pseudo code  would be much appreciated.
>
> > Thanks,
> > Rahul
>
> > --
> > 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<mockito%2Bunsu...@googlegroups.com>

Rahul

unread,
Jan 5, 2010, 10:11:18 PM1/5/10
to mockito
Hi Michael,

I guess this would solve the issue. But then I would have to change
the signature of the save() method.
If this was one method could have thought about it, but we have this
throughout the code base and it would become a major re-factoring
effort.

Thanks,
Rahul

On Jan 5, 7:27 pm, Michael Hackett <mhack...@kanayo.com> wrote:
> Rahul,
>
> You can't mock global objects (like the Singleton
> PersistenceManagerFactory), unless you can replace the instance it returns.
> Instead, you should pass the factory into the save method, or the
> constructor of the class the method belongs to. Then you can create a mock
> PersistenceManagerFactory and pass it in.
>
> Your test code might look something like this:
>
>    PersistenceManagerFactory mockFactory =
> mock(PersistenceManagerFactory.class);
>    PersistenceManager mockManager = mock(PersistenceManager.class);
>    when(mockManager).load(...) ...
>
> when(mockFactory).getPersistenceManager(any(A.class)).thenReturn(mockManager);
>
>    xxx.save(mockFactory, session, dto);
>
>    verify(...);
>
> Cheers,
> -- Michael
>

> 2010/1/5 Rahul <rahu...@gmail.com>

Michael Hackett

unread,
Jan 5, 2010, 10:56:05 PM1/5/10
to moc...@googlegroups.com
Well, you could pass the factory into the constructor of the class with the save method instead. That would probably result in fewer changes. That would be the way I would normally do it anyway, I was just demonstrating with the most local change.

It's going to very difficult to use Mockito if your objects instantiate or retrieve the service objects they use, instead of having them passed in. Otherwise, you're going to need a setInstance() method on your Singletons, just for testing, which I personally don't like, but might get you through until you can perform the necessary refactorings.

2010/1/5 Rahul <rah...@gmail.com>

Moandji Ezana

unread,
Jan 6, 2010, 8:11:41 AM1/6/10
to moc...@googlegroups.com
On Wed, Jan 6, 2010 at 4:56 AM, Michael Hackett <mhac...@kanayo.com> wrote:
Otherwise, you're going to need a setInstance() method on your Singletons, just for testing, which I personally don't like, but might get you through until you can perform the necessary refactorings.

That's what I would have suggested, except via reflection, so as not to have to add it to the API, where it could be abused. The real solution, of course, is proper dependency injection, as was said previously.

Moandji

Rahul

unread,
Jan 6, 2010, 10:21:38 AM1/6/10
to mockito
With PowerMock you can mock static, final methods/classes, this doesnt
solve the issue I have on hand.

Thanks,
Rahul

Rahul

unread,
Jan 6, 2010, 1:09:26 PM1/6/10
to mockito
>I don't think that static code can be mocked by Mockito. You probably have
>to do it at byte code level. PowerMock can do it for you. Perhaps this may
>help


On Jan 5, 9:56 pm, Michael Hackett <mhack...@kanayo.com> wrote:
>
> It's going to very difficult to use Mockito if your objects instantiate or
> retrieve the service objects they use, instead of having them passed in.
> Otherwise, you're going to need a setInstance() method on your Singletons,
> just for testing, which I personally don't like, but might get you through
> until you can perform the necessary refactorings.
>

Michael/kartik,
Will try a combination of what you guys have suggested.
Am using mockito-all-jvm14-1.8.0.jar as the we are using jdk 1.4.
Powermock 1.3 needs at least jdk1.5 due to the annotations. Any work
around for this?

Thanks,
Rahul

Kartik Kumar

unread,
Jan 6, 2010, 1:44:38 PM1/6/10
to moc...@googlegroups.com
Perhaps there is a download for Java 1.4 on Powermock. If not, you can ask on Powermock forums.

--
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.

szczepiq

unread,
Jan 6, 2010, 6:36:40 PM1/6/10
to moc...@googlegroups.com
Hi,

>Michael/kartik,
>Will try a combination of what you guys have suggested.
>Am using mockito-all-jvm14-1.8.0.jar as the we are using jdk 1.4.
>Powermock 1.3 needs at least jdk1.5 due to the annotations. Any work
>around for this?

You shouldn't do it. Add new constructor so that you can pass in the
dependency from the test (you can have this constructor
package-protected if you like).

Really, really, **really** it does not make any sense to apply fancy
frameworks, googling for advanced solutions when there is a very
simple way of achieving the goal: improve testability.

//existing constructor:
public Foo() {
this(PersistenceManagerFactory.getInstance());
}

//new constructor:
Foo(PersistenceManagerFactory factory)
{
this.factory = factory;
}

For any new code: **avoid accessing singletons directly**. Instead
pass in the instances (for example via constructor parameters). Read
Misko Hevery's blog entries about singletons.

Hope that helps.
Szczepan Faber
PS.
I wasn't shouting :) just my humble suggestions.

Rahul

unread,
Jan 7, 2010, 10:18:02 AM1/7/10
to mockito
>
> You shouldn't do it. Add new constructor so that you can pass in the
> dependency from the test (you can have this constructor
> package-protected if you like).
>
> Really, really, **really** it does not make any sense to apply fancy
> frameworks, googling for advanced solutions when there is a very
> simple way of achieving the goal: improve testability.
>
> //existing constructor:
> public Foo() {
>    this(PersistenceManagerFactory.getInstance());
>
> }
>
> //new constructor:
> Foo(PersistenceManagerFactory factory)
> {
>    this.factory = factory;
>
> }
>
> For any new code: **avoid accessing singletons directly**. Instead
> pass in the instances (for example via constructor parameters). Read
> Misko Hevery's blog entries about singletons.
>
> Hope that helps.
> Szczepan Faber
> PS.
> I wasn't shouting :) just my humble suggestions.
>
Szczepan,
Thanks for the tip. As it is PowerMock doesnt support jdk1.4.
Will make changes to the constructors.

Rahul

Reply all
Reply to author
Forward
0 new messages