4

I have the following code:

public Object parse(){
      ....
      VTDGen vg = new VTDGen();
      boolean parsed = vg.parseFile(myFile.getAbsolutePath(), false);
}

I am writing a unit test for this method. When I run the method without mocking VTDGen the parseFile method returns true. However, when I mock it with a spy, it returns false.

My test is as follows:

@Before
public void setup(){
     VTDGen vtgGen = new VTDGen();
     VTDGen vtgGenSpy = PowerMockito.spy(vtdGen);
     PowerMockito.whenNew(VTDGen.class).withNoArguments().thenReturn(vtdGenSpy);

}


@Test
public void myTest(){
    // when I run the test parseFile returns false
    // if I remove the mocking in the setup, parseFile returns true
}

I was under the impression that Mockito's spy objects should not change the behavior of wrapped objects, so why am I getting false instead of true?

vtd-xml-author
  • 3,319
  • 4
  • 22
  • 30
John B
  • 32,493
  • 6
  • 77
  • 98
  • I need more help from you, either in your myTest() method or in your parse() method or maybe VTDGen.parseFile(). You are creating a spy, but I don't see the verification code. Where does myFile come from? I probably don't need ALL of that information, but more than what you've given so far. – jhericks Nov 10 '11 at 17:20
  • Sorry for the late reply. Weekend stuff. `myTest` calls `parse` and `myFile` is passed in. The point is that if I comment out `PowerMockito.whenNew`, `vg.parseFile` returns `true` but with the `whenNew` in place (so the spy is used) `vg.parseFile` returns `false`. I thought the spy should just wrap a call to the actual instance, so why is the returned value different? – John B Nov 14 '11 at 13:53
  • So you're not doing any actual 'spying' on your spy right now? How do you know what `vg.parseFile` is returning? – jhericks Nov 14 '11 at 16:57
  • Debugger. The return from `parse` was not what I was trying to test but is preventing me from getting to the code I am testing. I pulled out everything else that might be affecting the test and got down to the spy causing the problem. – John B Nov 14 '11 at 17:07
  • Does `vtdGenSpy.parseFile(myFile.getAbsolutePath(), false)` (without PowerMockito) return `false` too? – szhem Nov 16 '11 at 21:11
  • No. Without the spy it returns true. With the spy it returns false. – John B Nov 16 '11 at 21:21
  • Sorry, did you really ask about calling `parseFile` on the `spy` without `PowerMockito` or ask about the actual code under test without the spy. – John B Nov 16 '11 at 21:22
  • @JohnB If you change the `whenNew ... thenReturn` call to return `vtgGen` does the same thing occur? –  Nov 18 '11 at 06:53
  • @Bringer128 with `thenReturn(vtgGen)` `parse` returns `true` as expected – John B Nov 18 '11 at 11:19

3 Answers3

1

Maybe it is because you are returning vtdGenMock not vtgGenSpy in

PowerMockito.whenNew(VTDGen.class).withNoArguments().thenReturn(vtdGenMock);

Garrett Hall
  • 29,524
  • 10
  • 61
  • 76
1

When spying on Powermocked classes you should use the PowerMockito.spy(...) method:

VTDGen vtgGenSpy = PowerMockito.spy(vtdGen);

Also ensure your version combinations of Mockito/Powermock are compatible. I'm using Mockito 1.8.5 and Powermock 1.4.10.

The following tests (TestNG) pass for me:

@PrepareForTest({VTDGen.class, Uo.class})
public class UoTest extends PowerMockTestCase {

    private VTDGen vtdGen;
    private VTDGen vtdGenSpy;
    private Uo unitUnderTest;

    @BeforeMethod
    public void setup() {
        vtdGen = new VTDGen();
        vtdGenSpy = PowerMockito.spy(vtdGen);
        unitUnderTest = new Uo();
    }

    @Test
    public void testWithSpy() throws Exception {
        PowerMockito.whenNew(VTDGen.class).withNoArguments().thenReturn(vtdGenSpy);

        boolean result = unitUnderTest.parse();

        assertTrue(result);
    }

    @Test
    public void testWithoutSpy() throws Exception {
        PowerMockito.whenNew(VTDGen.class).withNoArguments().thenReturn(vtdGen);

        boolean result = unitUnderTest.parse();

        assertTrue(result);
    }
}

For unit under test:

public class Uo {
    public boolean parse() {
        VTDGen vg = new VTDGen();
        return vg.parseFile("test.xml", false);
    }
}
orien
  • 2,130
  • 16
  • 20
  • I have tried it with `PowerMockito.spy` to no avail. How can I tell if Powermock / Mockito are compatible? I have using Mockito 1.8.5 and Powermock 1.4.9 (I don't have access to PowerMock 1.4.10). – John B Nov 18 '11 at 13:54
  • Looks like as of PowerMock 1.3.9, it supported Mockito 1.8.5 – John B Nov 18 '11 at 13:58
1

This was in orien's reply although sort of indirectly: Did you include @PrepareForTest(ClassCallingNewVTDGen.class)?

It's the class calling

new VTDGen()

that has to be prepared for test. In orien's answer, it is Uo.class

Source

Doug Moscrop
  • 4,479
  • 3
  • 26
  • 46