Junit External Resource @Rule Order
Asked Answered
N

3

7

I want to use multiple external resources in my test class, but I have a problem with ordering of external resources.

Here is code snippet :

public class TestPigExternalResource {

     // hadoop external resource, this should start first
     @Rule
     public HadoopSingleNodeCluster cluster = new HadoopSingleNodeCluster();

     // pig external resourcem, this should wait until hadoop external resource starts
     @Rule
     public  PigExternalResource pigExternalResource = new PigExternalResource(); 

     ...  
}

The problem is it tries to start pig before hadoop started, therefore I could not connect local hadoop single node cluster.

Is there any way to order rules of junit?

thanks

Natiha answered 4/10, 2013 at 7:11 Comment(3)
Is HadoopSingleNodeCluster class publicly available? As i use org.apache.hadoop.mapred.ClusterMapReduceTestCase, but it's not that stable.Grishilde
@Grishilde HadoopSingleNodeCluster is my own class, not available in hadoop distribution.Natiha
is it based on some existing codebase? I try to use cluster mapreduce testcase, but it launches external JVMs and that's a bit hard for debugging in some cases.Grishilde
L
11

You can use RuleChain.

@Rule
public TestRule chain= RuleChain.outerRule(new HadoopSingleNodeCluster())
                           .around(new PigExternalResource());
Lawler answered 24/10, 2013 at 16:33 Comment(0)
L
1

Why don't you wrap these two ExternalResources in your own ExternalResource that calls the before and after methods in the order you require from within the new resource's before and after methods.

Example:

public class MyResource extends ExternalResource{
     private final List<ExternalResource> beforeResources;
     private final List<ExternalResource> afterResources;

     public MyResource(List<ExternalResource> beforeResources,
          List<ExternalResource> beforeResources){
     }

      public void before(){
          for (ExternalResource er : beforeResources)
               er.before();
      }

      public void after(){
          for (ExternalResource er : afterResources)
               er.after();
      }
}


public class TestPigExternalResource {

 // hadoop external resource, this should start first
 public HadoopSingleNodeCluster cluster = new HadoopSingleNodeCluster();

 // pig external resourcem, this should wait until hadoop external resource starts
 public  PigExternalResource pigExternalResource = new PigExternalResource(); 

  @Rule
  public MyResource myResource = new MyResource(
          newArrayList(cluster, pigExternalResource),
          newArrayList(cluster, pigExternalResource));
 ...  
}
Louettalough answered 4/10, 2013 at 10:30 Comment(2)
Thanks but I guess using @Rule annotation in before and after method is not allowed.Natiha
See example added to post. The other resources would no longer be marked as rules since they would be included in the wrapping rule.Louettalough
T
1

There's a new order attribute in @Rule and @ClassRule as of JUnit 4.13-beta-1.

See @Rule code :

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Rule {

    int DEFAULT_ORDER = -1;

    /**
     * Specifies the order in which rules are applied. The rules with a higher value are inner.
     *
     * @since 4.13
     */
    int order() default DEFAULT_ORDER;

}

See also this PR for reference : PR-1445.

Terrorist answered 2/4, 2019 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.