how to mock the new object creation in the method

49242 views
Skip to first unread message

ML

unread,
Oct 10, 2011, 3:59:31 PM10/10/11
to mockito
I want to test the method using the mockito (not using annotations);


my method looks like this:

public void methodName(){
//do some logic

Object object = new Object(otherObject);
//do some logic


}


I want to test this function but I want to ignore -mock new object
creation somehow.

and the second question: can I mock static methods.
I have somewhere in the code Class.staticMethod that I would like to
mock.
Is that possible? I've read somewhere that's not possible with
mockito. is that true?
Thanks a lot.

Greg Silin

unread,
Oct 10, 2011, 4:10:17 PM10/10/11
to moc...@googlegroups.com
If you absolutely need to mock a constructor invocation, AFAIK the only way to do it is with Powermock framework's whenNew.  See more here: http://www.gitshah.com/2010/05/how-to-mock-constructors-using.html


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


Brice Dutheil

unread,
Oct 10, 2011, 4:19:50 PM10/10/11
to moc...@googlegroups.com
Yes it is not.

Mockito empowers lowly coupled object design, if you mock static methods or constructors you are creating coupled code. COupled design is known to be not good for evolutivity and maintainability. You really should avoid such design choices, and choose other alternatives.

For example if you want to avoid this object creation, why not instead inject a Factory or a Proxy (as in the GoF), or even Providers (such as in Guice).

Anyway in certain circumstances you might be forced to do that, and then Powermock will help.



-- 
Brice

David Wallace

unread,
Oct 11, 2011, 2:16:33 AM10/11/11
to mockito
I know of two really good ways of doing this with Mockito. Both
require rearranging your code a little, to make it more testable.
Writing code that's easily testable is a good thing to be doing,
regardless of which mocking framework you end up using.

Pattern 1 involves factoring uses of "new" into one-line methods, then
using a Mockito spy. This is the simpler of the two patterns.
Pattern 2 involves factoring uses of "new" into a separate class and
injecting it. It's a little more work, but it can be more powerful.
The "new" calls that you want to factor out (using either pattern) are
those where an object is created, that you are likely to want to
mock. I recommend using one or other of these patterns, whenever you
find yourself writing "new", on a class that's in your code base (as
opposed to a JDK class or a library class).

To use pattern 1 (testing a class called MyClass), you would replace a
call like
Foo foo = new Foo( a, b, c );
with
Foo foo = makeFoo( a, b, c );
and write a one-line method
protected Foo makeFoo( A a, B b, C c ){
return new Foo( a, b, c );
}
It's important that you don't include any logic in the method; just
the one line that creates the object. Then, when you come to test the
class, the object that you test will actually be a Mockito spy, with
this method overridden, to return a mock. So your test class might
contain members like
@Mock private Foo mockFoo;
private MyClass toTest = spy( new MyClass());

Lastly, inside your test method you mock out the call to makeFoo with
a line like
when( toTest.makeFoo( any( A.class ), any( B.class ),
any( C.class ))).thenReturn( mockFoo );
You can use matchers that are more specific than any() if you want to
check the arguments that are passed to the constructor.

Note that I haven't tested the code above, so it may contain typos,
but the basic pattern works.

One case where this pattern won't work is if MyClass is final. Most
of the Mockito framework doesn't play particularly well with final
classes; and this includes the use of spy(). Another case is where
MyClass uses getClass() somewhere, and requires the value of it to be
MyClass. This won't work, because the class of a spy is actually a
Mockito-generated subclass of the original class. In either of these
cases, you'll need the slightly more robust FactoryHelper pattern, as
follows (again, this may contain typos).

public class MyClass{
protected static class FactoryHelper{
Foo makeFoo( A a, B b, C c ){
return new Foo( a, b, c );
}
}

...

private FactoryHelper helper;
public MyClass( X x, Y y ){
this( x, y, new FactoryHelper());
}

protected MyClass( X x, Y, y, FactoryHelper helper ){

...

this.helper = helper;
}

...

Foo foo = helper.makeFoo( a, b, c );
}

So, you have a special constructor, just for testing, that has an
additional argument. This is used from your test class, when creating
the object that you're going to test. In your test class, you mock
the FactoryHelper class, as well as the object that you want to
create.

@Mock private MyClass.FactoryHelper mockFactoryHelper;
@Mock private Foo mockFoo;
private MyClass toTest;

and you can use it like this

toTest = new MyClass( x, y, mockFactoryHelper );
when( mockFactoryHelper.makeFoo( any( A.class ), any( B.class ),
any( C.class ))).thenReturn( mockFoo );

As before, you can use matchers that are more specific than any() if
you need to.

I realise I've skipped over some things, in an effort not to make this
post too long. Don't hesitate to ask if something is unclear. But
don't abandon Mockito because it lacks PowerMock's whenNew() - you
don't need it.

Hope this helps.
David.

ML

unread,
Oct 11, 2011, 3:35:43 PM10/11/11
to mockito
thank you, guys for your great comments and explanations. I've dot it
finally. =)
I've managed to run it using Mockito only and a little re-design of
code.
Your comments helped me a lot in that.
They've made me think a lot about the design of code I'm writing.
Definitely have to extend my knowledge in TDD.
Thanks you.



Jeff Vincent

unread,
Dec 20, 2012, 4:31:30 PM12/20/12
to moc...@googlegroups.com
I really like this list of things that help make code more testable, but it isn't always obvious how to implement these in all cases. Regardless there are some good concepts to think about...

http://googletesting.blogspot.com/2008/08/by-miko-hevery-so-you-decided-to.html

Brice Dutheil

unread,
Dec 21, 2012, 6:24:34 AM12/21/12
to moc...@googlegroups.com
Great pointer, Misko Hevery's blog is full of useful stuff, it brings back memories of this blog entry.

-- Brice


On Thu, Dec 20, 2012 at 10:31 PM, Jeff Vincent <preda...@gmail.com> wrote:
I really like this list of things that help make code more testable, but it isn't always obvious how to implement these in all cases.  Regardless there are some good concepts to think about...

http://googletesting.blogspot.com/2008/08/by-miko-hevery-so-you-decided-to.html
--
You received this message because you are subscribed to the Google Groups "mockito" group.
To view this discussion on the web visit https://groups.google.com/d/msg/mockito/-/CEejL8Ne0hYJ.

Eric Lefevre-Ardant

unread,
Jan 31, 2013, 5:19:21 AM1/31/13
to moc...@googlegroups.com
Yes, then when(mock.method()) pattern does not work well in those situations.

Try doReturn(output).when(spyEmailSender).makeFileOutputStream(anyString()) instead.

Eric

Le jeudi 31 janvier 2013, José Matias a écrit :
Hello great tips on refactoring, alltough i came to the following situation where my newly created
object can throw an exception, such as FileNotFoundException

so my testing code

EmailAlertsSender spyEmailSender = spy(new EmailAlertsSender());
FileOutputStream output = mock(FileOutputStream.class);

--> when(spyEmailSender.makeFileOutputStream(anyString())).thenReturn(output);

when invoking the 'when' throws a FileNotFoundException

@Override
public FileOutputStream makeFileOutputStream(String fileLocation) throws FileNotFoundException{
return new FileOutputStream(fileLocation);
}

allthough it works if i dont throw the exception

@Override
public FileOutputStream makeFileOutputStream(String fileLocation){
try {
return new FileOutputStream(fileLocation);
}
catch (FileNotFoundException e) {
return null;
}
}

i would like to be able to throw the exception, what can i do? 
Cheers

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.

To post to this group, send email to moc...@googlegroups.com.

Brice Dutheil

unread,
Jan 31, 2013, 8:25:45 AM1/31/13
to moc...@googlegroups.com
Yes that's how it should be done.

Here's why, for spies, the real code is executed by default, so when you write this line

when(spyEmailSender.makeFileOutputStream(anyString())).thenReturn(output);

Here's how it is decomposed :

String arg1 = anyString();
FileOutputStream fos = spyEmailSender.makeFileOutputStream(arg1);
when(fos).thenReturn(output);

So as this is a spy the real code of your method gets executed, and receive null from the anyString() matcher.

A contrario, if you use the other syntax that Eric suggested, the real code won't be executed while stubbing your interactions, because the mock is place in a specific mode before calling the stubbed method.


Hope that helps.

Always thank you Eric for monitoring the chan and helping people :)


-- Brice
Reply all
Reply to author
Forward
0 new messages