JUnit @Rule to pass parameter to test
Asked Answered
H

5

14

I'd like to create @Rule to be able to do something like this

@Test public void testValidationDefault(int i) throws Throwable {..}

Where i is parameter passed to the test by @Rule.

However I do get

java.lang.Exception: Method testValidationDefault should have no parameters

is there any way to bypass it and set the i parameter in the @Rule?

Horizon answered 17/6, 2010 at 10:1 Comment(2)
Is @Rule a JUnit provided annotation? Where is it supposed to be put?Skelton
FYI - I was using junit,hamcrest and junitparams jar files. I forgot to use this code @RunWith(JUnitParamsRunner.class) before my test class name. Then, I got the error you got - java.lang.Exception: Method testMethod should have no parameters.Jeffcott
H
-4

it can't be done, you can't pass parameters to test method even using @Rule.

Horizon answered 11/1, 2011 at 6:53 Comment(1)
See my response for a way to pass parameters, albeit without using @Rule.Starflower
A
12

As IAdapter said you can't pass an argument using Rules, but you can do something similar.

Implement a Rule that holds all your parameter values and evaluates the test once for every parameter value and offers the values through a method, so the test can pull them from the rule.

Consider a Rule like this (pseudo code):

public class ParameterRule implements MethodRule{
    private int parameterIndex = 0;
    private List<String> parameters;
    public ParameterRule(List<String> someParameters){ 
        parameters = someParameters;
    }

    public String getParameter(){
        return parameters.get(parameterIndex);
    }

    public Statement apply(Statement st, ...){
        return new Statement{
             public void evaluate(){
                 for (int i = 0; i < parameters.size(); i++){
                     int parameterIndex = i;
                     st.evaluate()
                 }      
             }
        }
    }
}

You should be able to use this in a Test like this:

 public classs SomeTest{
     @Rule ParameterRule rule = new ParameterRule(ArrayList<String>("a","b","c"));

     public void someTest(){
         String s = rule.getParameter()

         // do some test based on s
     }
 }
Adulthood answered 5/6, 2012 at 10:17 Comment(1)
I actually build a somewhat workable example from that: github.com/schauder/parameterizedTestsWithRulesAdulthood
A
8

I use @Parameters and @RunWith(value = Parameterized.class) for passing values to tests. An example can be found here.

I did not know about the @Rule annotation, but after reading this post, I think it serves another purpose than passing parameters to the tests:

If in your test class, you create a field pointing to an object implementing the MethodRule interface, and you mark this to be processed as a rule, by adding the @Rule implementation, then JUnit will call back on your instance for every test it will run, allowing you to add additional behavior around your test execution.

I hope this helps.

Algology answered 17/6, 2010 at 10:23 Comment(3)
That last url you gave cannot be found.Broadfaced
@Algology The link for additional example of how to use Rule annotation is broken. Update your answer.Thrifty
@Thrifty thank your for your comment: I removed the link to the additional example, because the author had apparently deleted the page.Algology
E
1

recently i started zohhak project. it lets you write tests with parameters (but it's a runner, not a rule):

@TestWith({
   "25 USD, 7",
   "38 GBP, 2",
   "null,   0"
})
public void testMethod(Money money, int anotherParameter) {
   ...
}
Erbes answered 5/12, 2012 at 15:55 Comment(0)
S
0

It should be noted that it is no longer true that you can't pass parameters directly to a test method. It can now be done using Theories and @DataPoints/@DataPoint.

For example:

@RunWith(Theories.class)
public class TestDataPoints {

    @DataPoints
    public static int [] data() {
        return new int [] {2, 3, 5, 7};
    }

    public int add(int a, int b) {
        return a + b;
    }

    @Theory
    public void testTheory(int a, int b) {
        System.out.println(String.format("a=%d, b=%d", a, b));
        assertEquals(a+b, add(a, b));
    }
}

Output:

a=2, b=2
a=2, b=3
a=2, b=5
a=2, b=7
a=3, b=2
a=3, b=3
a=3, b=5
a=3, b=7
a=5, b=2
a=5, b=3
a=5, b=5
a=5, b=7
a=7, b=2
a=7, b=3
a=7, b=5
a=7, b=7

With the test passing.

Starflower answered 13/12, 2011 at 19:54 Comment(3)
This doesn't allow to have several DataPoints, so this functionality is pretty useless in 99% of cases.Orose
You can have multiple @DataPoints. If they are of different types then they get handled automatically, if they are of the same type you can use a parameter supplier. Slightly cumbersome to set up, but relatively straightforward to use once you do so.Starflower
Still much more complicated and cumbersome than DataProviders in TestNG. Though it looks to be pretty obvious that this feature is very helpful..Orose
H
-4

it can't be done, you can't pass parameters to test method even using @Rule.

Horizon answered 11/1, 2011 at 6:53 Comment(1)
See my response for a way to pass parameters, albeit without using @Rule.Starflower

© 2022 - 2024 — McMap. All rights reserved.