Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple RunWith Statements in jUnit

I write unit test and want to use JUnitParamsRunner and MockitoJUnitRunner for one test class.

Unfortunately, the following does not work:

@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

Is there a way to use both, Mockito and JUnitParams in one test class?

like image 985
Hans-Helge Avatar asked Oct 06 '22 20:10

Hans-Helge


People also ask

Can we have multiple @RunWith?

You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element. So, what is the solution? The solution is to put only one @RunWith() with runner you cannot stand without and replace other one with something else.

What is RunWith JUnit?

When a class is annotated with @RunWith or extends a class annotated with @RunWith , JUnit will invoke the class it references to run the tests in that class instead of the runner built into JUnit. We added this feature late in development.

What is the use of @after in JUnit?

org.junit Annotating a public void method with @After causes that method to be run after the Test method. All @After methods are guaranteed to run even if a Before or Test method throws an exception.

What is JUnit runner class?

A JUnit Runner is a class that extends JUnit's abstract Runner class and it is responsible for running JUnit tests, typically using reflection.


1 Answers

You cannot do this because according to spec you cannot put the same annotation twice on the same annotated element.

So, what is the solution? The solution is to put only one @RunWith() with runner you cannot stand without and replace other one with something else. In your case I guess you will remove MockitoJUnitRunner and do programatically what it does.

In fact the only thing it does it runs:

MockitoAnnotations.initMocks(test);

in the beginning of test case. So, the simplest solution is to put this code into setUp() method:

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

I am not sure, but probably you should avoid multiple call of this method using flag:

private boolean mockInitialized = false;
@Before
public void setUp() {
    if (!mockInitialized) {
        MockitoAnnotations.initMocks(this);
        mockInitialized = true;  
    }
}

However better, reusable solution may be implemented with JUnt's rules.

public class MockitoRule extends TestWatcher {
    private boolean mockInitialized = false;

    @Override
    protected void starting(Description d) {
        if (!mockInitialized) {
            MockitoAnnotations.initMocks(this);
            mockInitialized = true;  
        }
    }
}

Now just add the following line to your test class:

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

and you can run this test case with any runner you want.

like image 122
AlexR Avatar answered Oct 10 '22 07:10

AlexR