Mocking Static Methods - java

As i did some research i have found out that PowerMock is able to mock static java methods.
Can someone explain (technically) what is PowerMock doing different than JUnit and others which can not or do not? And also why static methods are(were) causing issues when they are tried to mock?
thanks

http://blog.jayway.com/2009/05/17/mocking-static-methods-in-java-system-classes/
In order to mock an instance method, you can simply override it in a subclass. You can't do that with static methods because there's no "static polymorphism".
Powermock can do it because it works with bytecode, while other popular frameworks rely on polymorphism and create subclasses with CGLIB.
From the link: "Basically all standard mock frameworks use CGLib to create a mock object which means that they're based on a hierarchical model (CGLib creates a sub class of the class to test at run-time which is the actual mock object) instead of a delegation model which PowerMock uses through it's byte-code manipulation by delegating to the MockGateway."

Related

In JUnit-5, How do I mock a static method that returns void? Can we use import org.mockito.MockedStatic?

I have a few 3rd parties static util methods in my project, some of them just pass or throw an exception. There are a lot of examples out there on how to mock a static method using PowerMock but Junit5 doesn't support PowerMock, which has a return type other than void. But how can I mock a static method that returns void to just "doNothing()"?
Don't mock it. From your minimal description, you could replace the usage sites with Consumer and provide a mock of that. (You can even initialize the fields with method references to the static methods and just have setter methods to override them.)
However, the fact that the class under test calls these static methods is usually just an implementation detail that the test shouldn't care about, only checking observable behavior.
Build a wrapper class on it, call the wrapper method, and you can have a different wrapper in your test if you can do behavior differently or have the wrapper to call a class/method can be mocked ,

Making use of ReflectionTestUtils to mock a static class

I am writing unit test for a class which makes use of the static class ProcessTimer. To be precise, ProcessTimer.startTimer().
I am looking for a way to mock this call. I have used plain ReflectionUtils and PowerMock before, but I am wondering if I could do this with ReflectionTestUtils which comes from Spring.
If possible, I could remove the PowerMock dependencies and rewrite few other tests too. Any help is greatly appreciated!
ReflectionTestUtils is not for mocking. Rather, it is only for setting/reading non-public fields and invoking non-public methods.
If you want to mock what is returned by a static method you will have to use a dedicated mocking framework for that -- for example, something like PowerMock as you mentioned.
Regards,
Sam (author of ReflectionTestUtils)

Mockito and final equals() method in class - is it mockable?

I want to mock a class from other library using Mockito. I read that Mockito relies on specific (CGLIB provided I think) implementation of equals method. Unfortunately this outer class has equals() denoted with final modifier, and there is throwing exception in its body.
When I try to mock this class I always get exception from this method. CGLIB apparently doesn't get by with final, and real method is called.
Any ideas? What can I do, to mock this class using Mockito? Maybe other library will handle it?
[EDIT] quick explanation: I don't want to mock equals(), I check other methods. Problem is that mockito internally uses equals(), I don't know what for. As equals() is final, real method is called with exception throwing. I had hope that there is some setting in mockito "don't use equals()" :-)
Thanks for answers, I will read them closely tomorrow.
This matrix shows features supported by different frameworks:
External link to the matrix here.
According to this, only PowerMock and JMockit can mock final methods.
Mockito cannot mock final methods. Apparently PowerMock can though.
A hacky workaround could be to create a non-final method that delegates to the final equals method and mock that.
I believe that the steps to mock a final method with PowerMock and Mockito API would be: run your tests with the #RunWith(PowerMockRunner.class) then prepare the class you want to mock #PrepareForTest(ClassToBeMocked.class). After that, mock your object and use the when method to mock the equals method.
I think that it won't work if you do not use the PrepareForTest annotation in your test class.

Why doesn't Mockito mock static methods?

I read a few threads here about static methods, and I think I understand the problems misuse/excessive use of static methods can cause. But I didn't really get to the bottom of why it is hard to mock static methods.
I know other mocking frameworks, like PowerMock, can do that but why can't Mockito?
I read this article, but the author seems to be religiously against the word static, maybe it's my poor understanding.
An easy explanation/link would be great.
I think the reason may be that mock object libraries typically create mocks by dynamically creating classes at runtime (using cglib). This means they either implement an interface at runtime (that's what EasyMock does if I'm not mistaken), or they inherit from the class to mock (that's what Mockito does if I'm not mistaken). Both approaches do not work for static members, since you can't override them using inheritance.
The only way to mock statics is to modify a class' byte code at runtime, which I suppose is a little more involved than inheritance.
That's my guess at it, for what it's worth...
If you need to mock a static method, it is a strong indicator for a bad design. Usually, you mock the dependency of your class-under-test. If your class-under-test refers to a static method - like java.util.Math#sin for example - it means the class-under-test needs exactly this implementation (of accuracy vs. speed for example). If you want to abstract from a concrete sinus implementation you probably need an Interface (you see where this is going to)?
Mockito [3.4.0] can mock static methods!
Replace mockito-core dependency with mockito-inline:3.4.0.
Class with static method:
class Buddy {
static String name() {
return "John";
}
}
Use new method Mockito.mockStatic():
#Test
void lookMomICanMockStaticMethods() {
assertThat(Buddy.name()).isEqualTo("John");
try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
theMock.when(Buddy::name).thenReturn("Rafael");
assertThat(Buddy.name()).isEqualTo("Rafael");
}
assertThat(Buddy.name()).isEqualTo("John");
}
Mockito replaces the static method within the try block only.
As an addition to the Gerold Broser's answer, here an example of mocking a static method with arguments:
class Buddy {
static String addHello(String name) {
return "Hello " + name;
}
}
...
#Test
void testMockStaticMethods() {
assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
theMock.when(() -> Buddy.addHello("John")).thenReturn("Guten Tag John");
assertThat(Buddy.addHello("John")).isEqualTo("Guten Tag John");
}
assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
}
Mockito returns objects but static means "class level,not object level"So mockito will give null pointer exception for static.
I seriously do think that it is code smell if you need to mock static methods, too.
Static methods to access common functionality? -> Use a singleton instance and inject that
Third party code? -> Wrap it into your own interface/delegate (and if necessary make it a singleton, too)
The only time this seems overkill to me, is libs like Guava, but you shouldn't need to mock this kind anyway cause it's part of the logic... (stuff like Iterables.transform(..))
That way your own code stays clean, you can mock out all your dependencies in a clean way, and you have an anti corruption layer against external dependencies.
I've seen PowerMock in practice and all the classes we needed it for were poorly designed. Also the integration of PowerMock at times caused serious problems(e.g. https://code.google.com/p/powermock/issues/detail?id=355)
PS: Same holds for private methods, too. I don't think tests should know about the details of private methods. If a class is so complex that it tempts to mock out private methods, it's probably a sign to split up that class...
In some cases, static methods can be difficult to test, especially if they need to be mocked, which is why most mocking frameworks don't support them. I found this blog post to be very useful in determining how to mock static methods and classes.

How to mock object?

How to mock object for testing if the class you're testing is abstract? you can't instantiate from it ?
Mocking is creating a mock implementation of an interface or abstract class, and rarely of concrete classes. You can make these mocks at runtime using a mocking framework:
EasyMock
mockito
JMockIt
If you want to test the common implementation of your abstract class, then you should create a dummy concrete implementation in you test subsystem and just unit test the common methods of that class.
If, on the other hand, you need to pass around a reference to your abstract class, then, as Bozho has suggested, you should use a mocking framework. My favorite is JMock.
As Paddy mentions, you really want to test a concrete class.
But, if you want to test functionality provided by an abstract class, the common method for doing so is to create an abstract TestCase with an abstract method for providing the concrete class and then test the common functionality within your AbstractWhateverTestCase.
See http://c2.com/cgi/wiki?AbstractTestCases for some examples.

Categories