spy and private method

9,004 views
Skip to first unread message

jahid

unread,
Jul 1, 2009, 5:42:41 AM7/1/09
to mockito
Hi,

I was wondering how to mock a private method, or other methods of an
implementation while testing one specific method. I did not find any
specific private method mocking example. So I was trying with spy. I
created a spy of testing concrete class. And spied the method (made
the method default access level, because did not find any example of
mocking private method). So after that, when i was invoking the
testing method, it still invokes the mocked method. As an example -

class WantToTest {
public void sayHello(String name) {
printMessage(name, "Some internal message");
}

void String printMessage(String name, String internal message) {
sysout("hello "+name);
return "Hello "+name);
}
}

And my test looks like -

WantToTest spy=spy(new WantToTest());
when(printMessage(null, null)).thenReturn(null);

spy.sayHello("Jahid");




But it seems like, the mocked was not created for the "printMessage"
method. How I am sure? I get an exception. And to be sure I added a
break point inside that "printMessage" and control still hits that
breakpoint.



Any idea? and also any suggestion for private method mocking?

Bartosz Bańkowski

unread,
Jul 1, 2009, 5:52:00 AM7/1/09
to moc...@googlegroups.com
Hi,

First of all, you cannot mock private methods.

In your code you invoke:


printMessage(name, "Some internal message");

While your mock looks like that:
when(printMessage(null, null)).thenReturn(null);

It should be:
when(printMessage("Jahid", "Some internal
message")).thenReturn("something else");

Best regards,
Bartosz

jahid

unread,
Jul 1, 2009, 6:34:26 AM7/1/09
to mockito
HI,

Thanks for the reply. Now the question is, if I am mocking the whole
behaviour of the method, then what is the point whether I am passing
real object or null. Because those will never be used (since the
method is mocked). The second thing is, why it is still hitting the
break point? Since the method is mocked, the stub should just return
without even checking the parameters.

The point I am trying to make here is, may be the parameter is a big
complex object, and I dont want to spend time to construct it, and I
dont want to spend time to even mock it, because I mocked the whole
behaviour of the method. And I just want to concentrate on the testing
method.

Did i miss something? or what I am expectating is not right from some
point?


Regards,

Jahid




On Jul 1, 11:52 am, Bartosz Bańkowski <bbankow...@gmail.com> wrote:
> Hi,
>
> First of all, you cannot mock private methods.
>
> In your code you invoke:
> printMessage(name, "Some internal message");
>
> While your mock looks like that:
> when(printMessage(null, null)).thenReturn(null);
>
> It should be:
> when(printMessage("Jahid", "Some internal
> message")).thenReturn("something else");
>
> Best regards,
> Bartosz
>

jahid

unread,
Jul 1, 2009, 6:41:46 AM7/1/09
to mockito
Ohhh also, it seems like mockito did not mock my method. Because it
throws exception even if I pass mocked object (I mean not passing null
anymore to the mocked method) as parameter.

Any idea?

Bartosz Bańkowski

unread,
Jul 1, 2009, 6:42:31 AM7/1/09
to moc...@googlegroups.com
Mockito has to know which invocation you want to stub. You may want to
stub it with arguments "a" and "b" and invoke real method with any
other arguments.

What you look for are argument matchers (anyString() in your case).
Please, take a look at the documentation:
http://mockito.googlecode.com/svn/branches/1.7/javadoc/org/mockito/Matchers.html

when(printMessage(anyString(), anyString())).thenReturn("something");

Best regards,
Bartosz


2009/7/1 jahid <jsh...@gmail.com>:

Bartosz Bańkowski

unread,
Jul 1, 2009, 6:47:11 AM7/1/09
to moc...@googlegroups.com
Can you copy&paste full source code? The problem here is also that in
when() you are not using your spy, but I'm not sure if it is a typo or
is it a real cause.

Bartosz

2009/7/1 jahid <jsh...@gmail.com>:

jahid

unread,
Jul 1, 2009, 6:55:11 AM7/1/09
to mockito
The abstract class has a child class, and I am mocking that. That is
just an empty class. So I am pasting the abstract class. I have also
added the test afterwards -




public abstract class AbstractZipFileScannable implements Scannable {
private static final Log log = LogFactory.getLog
(AbstractZipFileScannable.class);

private File sourceFile;
private BundleManager bundleManager;
private ScanRecord lastBuild;
private ScanRecord lastPreBuild;

@Override
public void scan() {
if (!sourceFile.exists()) {
return;
}

ScanRecord tempBuild = new ScanRecord();
tempBuild.setTarget(sourceFile);

if (lastPreBuild == null) {
lastPreBuild = tempBuild;
return;
}

if (lastPreBuild.equals(tempBuild)) {
if (lastBuild.getLastModified() < lastPreBuild.getLastModified()) {
File tempExtractedDirectory = new File(System.getProperty
("java.io.tmpdir") + File.separator + System.currentTimeMillis() + "_"
+ sourceFile.getName());
File extractedLocation = extract(sourceFile,
tempExtractedDirectory);
lastPreBuild = null;
lastBuild = tempBuild;
sourceFile.delete();
bundleManager.distributeEvent(extractedLocation);
}
} else {
lastPreBuild = tempBuild;
}
}

public void preScanStarts() {
if (sourceFile != null && sourceFile.exists()) {
sourceFile.delete();
}
}

File extract(File sourceZipFile, File extractedDirectory) {

FileUtil.deleteDirectory(extractedDirectory);
try {
ZipManager zipManager = new ZipManager();
zipManager.explodeArchive(sourceZipFile, extractedDirectory.getPath
());
} catch (IOException e) {
log.error(e);
e.printStackTrace();
// throw new RuntimeException(e);
}
return extractedDirectory;
}

public void setSourceFile(File sourceFile) {
Validate.notNull(sourceFile, "Source zip file can not be null");
this.sourceFile = sourceFile;
ScanRecord scanTarget=new ScanRecord();
scanTarget.setTarget(sourceFile);
this.lastBuild=scanTarget;
}

public void setBundleManager(BundleManager bundleManager) {
this.bundleManager = bundleManager;
}
}








ublic class TestZipBundleScannable {
@Mock
private BundleManager bundleManager;
private PDIBundleScannable pdiBundleScannable;

@Before
public void init() {
pdiBundleScannable = new PDIBundleScannable();
pdiBundleScannable.setBundleManager(bundleManager);
}

@Test
public void testScan() {
File sourceFile = mock(File.class);
when(sourceFile.lastModified()).thenReturn(10l);
when(sourceFile.length()).thenReturn(100l);
when(sourceFile.exists()).thenReturn(true);
when(sourceFile.delete()).thenReturn(true);

// make initial call
pdiBundleScannable.setSourceFile(sourceFile);

PDIBundleScannable spy=spy(pdiBundleScannable);
doReturn(sourceFile).when(spy).extract(sourceFile, sourceFile);
//when(spy.extract(sourceFile, sourceFile)).thenReturn(sourceFile);

//deleting the file, so returning false
when(sourceFile.exists()).thenReturn(false);
spy.scan();

//considering new file is being copied (but not totally copied)
when(sourceFile.exists()).thenReturn(true);
when(sourceFile.lastModified()).thenReturn(12l);
when(sourceFile.length()).thenReturn(10l);
spy.scan();

//considering file copy is done
when(sourceFile.lastModified()).thenReturn(15l);
when(sourceFile.length()).thenReturn(101l);
spy.scan();

//two consecutive invocation to indicate its done
spy.scan();
}
}



In the scan method, there is "extract" method, which is invoked, and
that's the one i mocked. so that i can only check the scan method.
Sorry if I was doing something wrong. I tried to go by the examples
given on mockito site.



Thanks again.




On Jul 1, 12:47 pm, Bartosz Bańkowski <bbankow...@gmail.com> wrote:
> Can you copy&paste full source code? The problem here is also that in
> when() you are not using your spy, but I'm not sure if it is a typo or
> is it a real cause.
>
> Bartosz
>
> 2009/7/1 jahid <jsho...@gmail.com>:

jahid

unread,
Jul 1, 2009, 6:56:14 AM7/1/09
to mockito
And the stack trace looks like ---

java.lang.NullPointerException
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:114)
at java.util.zip.ZipFile.<init>(ZipFile.java:131)
at com.dts.app.bundlemanager.impl.ZipManager.explodeArchive
(ZipManager.java:57)
at
com.dts.app.bundlemanager.impl.sourcefileprovider.AbstractZipFileScannable.extract
(AbstractZipFileScannable.java:62)
at
com.dts.app.bundlemanager.impl.sourcefileprovider.AbstractZipFileScannable.scan
(AbstractZipFileScannable.java:40)
at
com.dts.app.bundlemanager.impl.sourcefileprovider.AbstractZipFileScannable
$$FastClassByMockitoWithCGLIB$$e8aecd70.invoke(<generated>)
at org.mockito.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.mockito.internal.MockHandler.intercept(MockHandler.java:97)
at org.mockito.internal.creation.MethodInterceptorFilter.intercept
(MethodInterceptorFilter.java:46)
at
com.dts.app.bundlemanager.impl.sourcefileprovider.PDIBundleScannable$
$EnhancerByMockitoWithCGLIB$$498af337.scan(<generated>)
at
com.dts.app.bundlemanager.impl.sourcefileprovider.TestZipBundleScannable.testScan
(TestZipBundleScannable.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod
(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:
79)
at
org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters
(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:
77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod
(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods
(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run
(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected
(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected
(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run
(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run
(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run
(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run
(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:197)

Bartosz Bańkowski

unread,
Jul 1, 2009, 8:57:54 AM7/1/09
to moc...@googlegroups.com
Looking briefly at the code I can see that in AbstractZipFileScannable you have:

File tempExtractedDirectory = new File(System.getProperty
("java.io.tmpdir") + File.separator + System.currentTimeMillis() + "_"
+ sourceFile.getName());
File extractedLocation = extract(sourceFile, tempExtractedDirectory);

While in the test you're trying to do something like that:
doReturn(sourceFile).when(spy).extract(sourceFile, sourceFile);

The second argument of extract() method is not sourceFile as shown
above. As it depends on current time, you should either refactor the
code or use anyObject() or any(File.class):
doReturn(sourceFile).when(spy).extract(eq(sourceFile), anyObject());

Best regards,
Bartosz

2009/7/1 jahid <jsh...@gmail.com>:
>

jahid

unread,
Jul 1, 2009, 9:09:50 AM7/1/09
to mockito
Hi Bartosz,

Thank you for your reply. I have made my changes as you have
mentioned. Which is -


AbstractZipFileScannable spy=spy(pdiBundleScannable);
doReturn(sourceFile).when(spy).extract(eq(sourceFile), any
(File.class));

Here I want to mention that, I did not change my source ( I mean, it
is as it was). But still I am getting the same error. It breaks when I
am calling extract method.


Regards,







On Jul 1, 2:57 pm, Bartosz Bańkowski <bbankow...@gmail.com> wrote:
> Looking briefly at the code I can see that in AbstractZipFileScannable you have:
>
>  File tempExtractedDirectory = new File(System.getProperty
> ("java.io.tmpdir") + File.separator + System.currentTimeMillis() + "_"
> + sourceFile.getName());
> File extractedLocation = extract(sourceFile, tempExtractedDirectory);
>
> While in the test you're trying to do something like that:
> doReturn(sourceFile).when(spy).extract(sourceFile, sourceFile);
>
> The second argument of extract() method is not sourceFile as shown
> above. As it depends on current time, you should either refactor the
> code or use anyObject() or any(File.class):
> doReturn(sourceFile).when(spy).extract(eq(sourceFile), anyObject());
>
> Best regards,
> Bartosz
>
> 2009/7/1 jahid <jsho...@gmail.com>:

Bartosz Bańkowski

unread,
Jul 1, 2009, 9:24:12 AM7/1/09
to moc...@googlegroups.com
Which version of Mockito are you using? Keep it mind that spy() worked
differently prior to version 1.8.

Best regards,
Bartosz

2009/7/1 jahid <jsh...@gmail.com>:

jahid

unread,
Jul 1, 2009, 9:28:07 AM7/1/09
to mockito
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.0-rc2</version>
<scope>test</scope>
</dependency>



On Jul 1, 3:24 pm, Bartosz Bańkowski <bbankow...@gmail.com> wrote:
> Which version of Mockito are you using? Keep it mind that spy() worked
> differently prior to version 1.8.
>
> Best regards,
> Bartosz
>
> 2009/7/1 jahid <jsho...@gmail.com>:
> ...
>
> read more >>

szczepiq

unread,
Jul 1, 2009, 2:48:53 PM7/1/09
to moc...@googlegroups.com
What if you tried using real file instead of mocking it?

Cheers,
Szczepan Faber

2009/7/1 jahid <jsh...@gmail.com>:

jahid

unread,
Jul 2, 2009, 1:46:00 AM7/2/09
to mockito
Hi szczepiq,

I did not understand what did you mean by "file". By real file did you
mean, not mokcing the extract method? If you meant so, inside that
method I am instantiating another class called ZipManager, which I
have to mock too. Also that variable is local to that method, and I do
not know how to mock local variable in mockito.


Regards,



On Jul 1, 8:48 pm, szczepiq <szcze...@gmail.com> wrote:
> What if you tried using real file instead of mocking it?
>
> Cheers,
> Szczepan Faber
>
> 2009/7/1 jahid <jsho...@gmail.com>:
> ...
>
> read more >>

jahid

unread,
Jul 2, 2009, 5:29:32 AM7/2/09
to mockito
Well, with the help of someone who is powermock expert, I just solve
the problem with one line,

PowerMock.suppressMethod(AbstractZipFileScannable.class, "extract");

(If anyone needs some little explanation, what's going on there.
Then:

Power mock is supressing all invocation to that private method named
"extract". Since I don't bother what is the return value, so I just
supressed all call. Otherwise of course we could add behaviour to
return value if we wanted to)


Thanks a lot guys!

szczepiq

unread,
Jul 2, 2009, 7:53:46 AM7/2/09
to moc...@googlegroups.com
> I did not understand what did you mean by "file".

I meant this file (a snippet from your test code):

File sourceFile = mock(File.class);

cheers
szczepan

2009/7/2 jahid <jsh...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages