I have a parent class that makes calls to external static methods and
in general makes life difficult. I tried the following:
@RunWith(PowerMockRunner.class)
public class IpFlexTableTest
extends
TestCase
{
@PrepareOnlyThisForTest(IpFlexTable.class)
public final void testIpFlexTable() throws Exception
{
final Constructor<FlexTable> defaultConstructor =
FlexTable.class.getConstructor((Class<?>[]) null);
suppress(defaultConstructor);
new IpFlexTable();
}
}
and this works fine, the IpFlexTable doesn't call its parent's
(FlexTable) constructor. So far so good.
I then tried
@RunWith(PowerMockRunner.class)
public class IpFlexTableTest
extends
TestCase
{
@PrepareOnlyThisForTest(IpFlexTable.class)
public final void testSetWidgetIntIntIsWidget() throws Exception
{
final FlexTable mockFlexTable = mock(FlexTable.class);
final Constructor<FlexTable> defaultConstructor =
FlexTable.class.getConstructor((Class<?>[]) null);
whenNew(defaultConstructor).withNoArguments().thenReturn(mockFlexTable);
final IpFlexTable ipFlexTable = new IpFlexTable();
}
}
which does *not* work (IpFlexTable now still runs through its normal
set of parent constructors). It was my understanding that in this case
IpFlexTable's parent would be the mock object. This is not the case?
For clarity, IpFlexTable is simply a wrapper around FlexTable:
public class IpFlexTable
extends
FlexTable
implements
HasFlexTable
{
@Override
public void setWidget(final int row, final int column, final IsWidget widget)
{
setWidget(row, column, widget.asWidget());
}
}
allowing me to use the HasFlexTable interface in other places to
facilitate testing. The only thing I'm trying to do in my IpFlexTable
test is assure that IpFlexTable.setWidget calls FlexTable.setWidget
with the correct arguments. How can I achieve this?
(PowerMock 1.4.6, Mockito 1.8.5, JUnit 4.8.2.)
Cheers,
Hilco
suppress(constructor(FlexTable.class));
--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To post to this group, send email to powe...@googlegroups.com.
To unsubscribe from this group, send email to powermock+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/powermock?hl=en.
On 23 November 2010 23:24, Johan Haleby <johan....@gmail.com> wrote:
> First off all thanks for the detailed problem description, it makes it much
> easier to help out. The short answer to your question is that
> (unfortunately) PowerMock cannot mock calls to super metods (see issue 51).
> I remember I tried to implement it a couple of years back but I couldn't
> find a good way to achieve it. We should probably give it another go though.
Understood. So what does whenNew do then? What happened to the mock I
told it to return?
> What you could do instead (which may actually be better) is to do state
> verification. If setWidget in FlexTable changes some state you could just
> verify that the state changes correctly which means that you don't need to
> mock the method. You can make use if the Whitebox class in powermock-reflect
> to get private (internal) state easily.
:-) If I could do that I would not have a need for PowerMock.
FlexTable depends on a whole hierarchy of other classes. These classes
have native methods and call static methods in other classes. It's a
nightmare. I can't do "new FlexTable()" because it calls those
native/static methods. Hence my attempt at circumventing that
constructor.
It all works at runtime but the only way to get it to work at "test
time" is to use a special TestCase extension which turns a subsecond
unit test into a 30+ second one. That's just plain unacceptable.
This is a bit of a setback because I'm very close. I've been able to
hide all these problems in a single package with a few wrapper
classes. Everything else now uses interfaces and is easy to test. I'll
have to rethink my strategy. Ideas are welcome. :-)
> Another thing, I think it's better if you make use of the methods in the
> MemberMatcher class in PowerMock when suppressing the constructor. Then you
> can write:
>
> suppress(constructor(FlexTable.class));
In this particular case, that would probably work because FlexTable
only has a single constructor. And it's how I started out because I
followed the tutorial. :-) But as soon as a class has more than one
constructor this seemed to break down. Even when I thought I had
indicated precisely which constructor to use it would complain about
finding more than one. So I gave up and simply used something that was
guaranteed to work.
Cheers,
Hilco
Cheers,
Hilco
Okay, that's useful.
> Have a look at the available methods in MemberMatcher class.
> Another thing, you can't use whenNew to return a mock of a super type!?
Is that a question or a statement?
> You
> can suppress the methods if you like or
> suppress(everythingDeclaredIn(FlexTable.class)).
I had not noticed this possibility. This could be a real time saver.
> You can also replace a
> method with an invocation handler in which you can do whatever you like:
> replace(method(FlexTable.class, "methodOfInterest")).with(new
> InvocationHandler() { // Method is intercepted here });
Yes, I already tried to use this. It didn't work in my case but it
seems very useful.
Cheers,
Hilco