@RunWith (PowerMockRunner.class) vs @RunWith (MockitoJUnitRunner.class)

In the usual mockery with @Mock and @InjectMocks test class should start with @RunWith(MockitoJUnitRunner.class) .

 @RunWith(MockitoJUnitRunner.class) public class ReportServiceImplTestMockito { @Mock private TaskService mockTaskService; @InjectMocks private ReportServiceImpl service; // Some tests } 

but in some example I use @RunWith(PowerMockRunner.class) :

 @RunWith(PowerMockRunner.class) public class Tests { @Mock private ISomething mockedSomething; @Test public void test1() { // Is the value of mockedSomething here } @Test public void test2() { // Is a new value of mockedSomething here } } 

could anyone indicate what the difference is and when I want to use one instead of the other?

+15
java mockito mocking powermockito
source share
3 answers

At first glance, the answer is simple: well, there are several mocking frameworks, and there are different ways to use them.

The first example tells JUnit to use the “unit testing module” that the Mockito Mocking framework provides. The second example uses a unit testing module from PowerMock.

To make everything clear, you should also have different import statements, since both platforms have different implementations, for example, for @Mock annotation.

(The main point of using these framework-specific tests is that they take care of initializing all the fields with special annotations specific to the framework).

So, the difference here is simply that the first example is written using the Mockito infrastructure, and the second uses PowerMock.

Now which one to use?

Answer: Mokito.

What for? The ugly truth is that PowerMock-one is a cry for help. It says that "the test class is poorly designed, please fix it."

Meaning: As a developer, you can write "easy to test" code or "difficult to test" code. Many people do the second thing: they write code that is difficult to test. And then PowerMock (ito) provides tools for testing this code.

PowerMock (ito) gives you the ability to simulate (thus control) calls to static methods and new() . To enable this, PowerMock (ito) manipulates the byte code of the test code. This is great for small codebases, but when you come across millions of lines of production code and thousands of unit tests, it's completely different. I saw that many PowerMock tests failed for no apparent reason, several hours later, to find out that some kind of “static” thing was changed somewhere else, and this somehow affects another static / new managed PowerMock test case.

At some point, our team made an informed decision: when you write new code, and you can only check it with PowerMock ... this is unacceptable. Since then, we have been creating only Mockito test suites, and since then we have never had strange problems that interfered with us with PowerMock.

The only acceptable reason to use PowerMock is when you want to test existing (possibly third-party) code that you do not want to modify. But of course, what's the point of testing such code? If you cannot change this code, why should the tests fail suddenly?

+20
source share

PowerMock should never be your first choice. If you just wrote a class that can only be tested with PowerMock, you did something wrong. A class must have a dependency injection or constructor with dependencies, so testing is easier and, of course, do not try to use static methods, since they are not fake in normal environments (read: mockito).

On the other hand: if you have a large project and you want to add unit tests to it, because the previous developer did not do this, PowerMock may be the only solution without completely refactoring everything. And from this perspective, I prefer PowerMock to no tests at all .

PowerMock is dirty because it modifies the bytecode, and code coverage using JaCoCo (the SonarQube coverage slider) does not work, but the IntelliJ code coverage slider works with PowerMock.

When in one class one method cannot be tested with Mockito, I separate the test: one test class with Mockito and one test class with PowerMock. This will provide the best code coverage in SonarQube.

 public class ClassToTest { public void testableMethod() { /* Do something */ } public String methodWithStaticCall() { return MyTest.staticMethod(); } } 

Then I have one class to test the first method:

 @RunWith(MockitoJUnitRunner.class) public class testClassToTest() { private sut = new ClassToTest(); @Test public testMethod() { sut.testableMethod(); } } 

And one with PowerMock:

 @RunWith(PowerMockJUnitRunner.class) @PrepareForTest({MyTest.class, ClassToTest.class}) public class testClassToTestPM() { private sut = new ClassToTest(); @Before public void before() { mockStatic(MyTest.class); } @Test public testMethod() { mockStatic(MyTest.class); when(MyTest.staticMethod()).thenReturn("test"); assertEquals("test", sut.methodWithStaticCall()); } } 
+1
source share

PowerMock allows you to simulate static and private methods, as well as final classes and more.

PowerMock is an environment that extends other mock libraries, such as EasyMock with more powerful features. PowerMock uses classloader and bytecode to include a mockery of static methods, constructors, final classes and methods, private methods, removing static initializers, and more.

There might be some code smell if you need to mock these types of components , but may be useful. At some point, you can work in an outdated project that created static helper classes that have dependencies that need to be mocked . If you have the opportunity to change the architecture, fix the design ! Otherwise, use the right technology for your tests.

If you don’t need to mock static or private functions, you don’t need to use PowerMock. PowerMock is a wrapper around other mocking frameworks.

0
source share

All Articles