gordonad / powermock

Automatically exported from code.google.com/p/powermock
0 stars 0 forks source link

Mock final methods of system class #135

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Mock final method getString() of system abstract class ResourceBundle:
ResourceBundle rb = PowerMock.createMock(ResourceBundle.class);
EasyMock.expect(rb.getString(EasyMock.eq("key"))).andReturn("value");
...

What is the expected output? What do you see instead?
I'd expect that rb.getString("key") returns "value", as defined in the mock
expectations.
Instead, the call to expect() throws an exception because the original
ResourceBundle.getString() is called, and this throws a
MissingResourceException because it's empty.

What version of the product are you using? On what operating system?
powermock 1.2.5, on Solaris 10 (Java 1.5.0_17)

Please provide any additional information below.

Original issue reported on code.google.com by danmar...@tin.it on 28 Jul 2009 at 3:56

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Unfortunately we don't have support for mocking instance methods of final system
classes yet. This is quite difficult because PowerMock is using a classloader 
and
there's no way for PowerMock to change the byte-code of a class loaded by Java
bootstrap CL. I've experimented with a work-around but I didn't quite get it to 
work
back then, but it should be possible in a future release.

Original comment by johan.ha...@gmail.com on 28 Jul 2009 at 8:27

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago

Original comment by johan.ha...@gmail.com on 7 Aug 2009 at 6:16

GoogleCodeExporter commented 8 years ago
We now support mocking of instance methods in final system classes. The same
mechanism could be used for mocking final methods in non-final system classes 
as well
but the problem is how the API should be designed. We could of course add a 
method
only for this purpose but it doesn't feel quite right. We'll have to think 
about this..

Original comment by johan.ha...@gmail.com on 13 Aug 2009 at 8:45

GoogleCodeExporter commented 8 years ago
I have the same problem mocking a SocketChannel instance (e.g. 
#configureBlocking()). Is this still a problem or am I just doing something 
wrong?

Original comment by koraktor on 9 Apr 2012 at 8:57

GoogleCodeExporter commented 8 years ago
Any progress on this issue?

Original comment by jonatan....@softhouse.se on 31 May 2013 at 5:01

GoogleCodeExporter commented 8 years ago
Yes I think this is supported, see 
https://code.google.com/p/powermock/wiki/MockSystem.

Original comment by johan.ha...@gmail.com on 1 Jun 2013 at 3:17

GoogleCodeExporter commented 8 years ago
That's for static methods. What about instance methods? I think that is what 
this issue is addressing as it says "final" methods. A static final method 
makes very little sense:)

Original comment by jonatan....@softhouse.se on 1 Jun 2013 at 3:51

GoogleCodeExporter commented 8 years ago
It's the same for instance methods.

Original comment by johan.ha...@gmail.com on 1 Jun 2013 at 6:43

GoogleCodeExporter commented 8 years ago
Ahh, cool. I tried it with StringBuilder and it worked in a simple scenario. 
When I tried to cast the mocked StringBuilder into an Appendable it stopped 
working though.

So the code I'm trying to get coverage for is:
{{{
    try
    {
        printOn((Appendable) target);
    }
    catch(IOException impossible)
    {
        throw new AssertionError(impossible);
    }
}}}

Any thoughts?

Original comment by jonatan....@softhouse.se on 8 Jun 2013 at 10:52

GoogleCodeExporter commented 8 years ago
So the isolated code looks like:
@RunWith(PowerMockRunner.class)
@PrepareForTest({NastyStringBuilder.class})
public class SomeTest
{
    @Test
    public void testThat() throws Exception
    {
        StringBuilder stringBuilder = NastyStringBuilder.thatThrows(new IOException());
        stringBuilder.length();
    }
}

public class NastyStringBuilder
{
    public static StringBuilder thatThrows(final IOException exceptionToThrow)
    {
        StringBuilder nastyBuilder = mock(StringBuilder.class);
        Answer<StringBuilder> withThrow = new Answer<StringBuilder>(){
            @Override
            public StringBuilder answer(InvocationOnMock invocation) throws Throwable
            {
                throw exceptionToThrow;
            }
        };
        PowerMockito.when(nastyBuilder.length()).thenAnswer(withThrow);
        return nastyBuilder;
    }
}

This code works, but when 
StringBuilder stringBuilder

is changed to
CharSequence stringBuilder

it stops working. I also tried String/CharSequence and they have the same issue.

It seems like javaassist isn't adding a javaassist.runtime.Desc interceptor. 
I'll debug it some more.

Original comment by jonatan....@softhouse.se on 9 Jun 2013 at 11:50

GoogleCodeExporter commented 8 years ago
The issue is that:
Modifier.isFinal(declaringClass.getModifiers()) 
in:
PowerMockExpressionEditor#shouldTreatAsSystemClassCall

only checks the compile time class (CharSequence), which isn't final, and not 
the runtime class (StringBuilder), which is final. Shouldn't all calls be 
wrapped with the MockGateway? I don't see how this could be determined at 
compile-time.

Original comment by jonatan....@softhouse.se on 9 Jun 2013 at 12:12

GoogleCodeExporter commented 8 years ago
always setting requiredByModifier to true made by testcase pass at least.

Original comment by jonatan....@softhouse.se on 9 Jun 2013 at 12:16

GoogleCodeExporter commented 8 years ago
This bug was introduced with 
http://code.google.com/p/powermock/source/detail?r=1524&path=/trunk/core/src/mai
n/java/org/powermock/core/transformers/impl/MainMockTransformer.java

Original comment by jonatan....@softhouse.se on 9 Jun 2013 at 12:33

GoogleCodeExporter commented 8 years ago
Thanks for your investigations. Could you create a patch (and test) for this? 
I'll try to release a new version soon.

Original comment by johan.ha...@gmail.com on 9 Jun 2013 at 1:13

GoogleCodeExporter commented 8 years ago
Sure. I'll fix it later tonight.

Original comment by jonatan....@softhouse.se on 9 Jun 2013 at 3:48

GoogleCodeExporter commented 8 years ago
I created #445 as I couldn't attach the patch file here.

"mvn verify" failed directly after checkout due to #387. Eclipse failed to 
build some projects due to "The method when(String) is ambiguous for the type 
WhenNewTest". Probably also due to me having jdk 1.7 installed. Blasphemy. So 
if you run the tests for me I'd appreciate it:)

Original comment by jonatan....@softhouse.se on 9 Jun 2013 at 11:55

GoogleCodeExporter commented 8 years ago
Thanks, I'll take a look at issue 445

Original comment by johan.ha...@gmail.com on 10 Jun 2013 at 5:15