Multiple Runwith Statements in Junit

Multiple RunWith Statements in jUnit

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.

Multiple runwith for a junit test class

You can't use two runners as it noted in the commented post. You should use the Parameterized runner as use Spring's TestContextManager to load the Spring context.

@Before 
public void before() throws Exception {
new TestContextManager(getClass()).prepareTestInstance(this);
}

how to combine @RunWith with @RunWith(Parameterized.class)

I believe this does what you want:

package so.junit.runner;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.model.InitializationError;
import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters;
import org.junit.runners.parameterized.ParametersRunnerFactory;
import org.junit.runners.parameterized.TestWithParameters;

import java.util.Arrays;

@RunWith(Parameterized.class)
@Parameterized.UseParametersRunnerFactory(CustomParameterizedTest.RunnerFactory.class)
public class CustomParameterizedTest {

@Parameterized.Parameters
public static Iterable<Integer> data() {
return Arrays.asList(new Integer[]{1, 2, 3});
}

private int i;

public CustomParameterizedTest(int i) {
this.i = i;
}

@Test
public void test() {
System.out.println(i);
}

public static class RunnerFactory implements ParametersRunnerFactory {
@Override
public org.junit.runner.Runner createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
return new A(test);
}
}

public static class A extends BlockJUnit4ClassRunnerWithParameters {
private final Object[] parameters;

public A(TestWithParameters test) throws InitializationError {
super(test);
parameters = test.getParameters().toArray(new Object[test.getParameters().size()]);
}

@Override
public Object createTest() throws Exception {
return getTestClass().getOnlyConstructor().newInstance(parameters);
}
}
}

Based on the Javadocs in the JUnit Parameterized class, this is how they expect you to create a custom test runner that supports parameterization.

UPDATE

Updated to name the custom runner A

Multiple RunWith Statements in jUnit

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.

Junit testing with multiple if statements

Well, in the real world, you would rather work the other way round: you would do TDD. Meaning: you think about an (ideally small) feature that your production code should have. Then you write a test for that, and you check that the test fails. Then you implement the feature, and now the test should pass.

Writing tests "after the facts" is most often less helpful. But in general: not a big deal. You can look at your code, and observe what is doing. Then you write tests to check that behavior.

Like:

@Test(expected=IllegalArgumentException.class)
public void testWithNegativeCapacity() {
new HashMap<String, String>(-1, 0.5);
}

First you write tests that check that your code that validates inputs throws up as expected.

Then you would continue, for example like

@Test
public void testForExpectedCapacity() {
assertThat(new HashMap<String, String>(10, 0.5).getCapacity(), is(whatever));
}

Where:

  • assertThat is one of the many "asserts" that you can use
  • is() is a hamcrest matcher that you use with assertThat, leading to readable test code
  • whatever would be the value you expect that the capacity is when calling that constructor with 10 and 0.5 (I am to lazy to compute the real expected result)

Finally: of course you can look at the implementation of the production code to derive tests. But you should also look at the contract of that code.

For example its documentation: try to understand what the code is supposed to do, and write tests that verify if these claims "when you do this, code does that" really hold.

Both sides are important, and only together you can get to a complete test suite. You want to ensure that the code does what it should do, and you want to verify that "how it is done" is correct!



Related Topics



Leave a reply



Submit