Using multiple TestRules in the same test
Asked Answered
K

3

6

I have written a custom TestRule to use with my Android test suite. It populates a table in the database used by the app under test. Now I need to use this DataRule along with ActivityTestRule. Can I have two fields of my test class annotated with @Rule? How do I control the order in which the rules are applied?

Background:

The Android API provides a TestRule for starting an Activity which is the core class for every app with a UI. My app has a database and I have several tests which require the database to be pre-populated with some known data. Previously, with JUnit3-based tests, I used an abstract superclass to centralize the code which prepares the database and then I extended this superclass for different test cases. Now I am trying to implement the same logic using JUnit 4. I learned recently that test rules are one way to provide logic which is reused across tests, so I am trying to move the logic from my superclass to a test rule. Is this an appropriate way to achieve my goal?

Kiona answered 12/2, 2016 at 22:28 Comment(0)
F
11

You certainly can have multiple @Rule fields in a single test. I'm not sure what the default ordering of rule application is, or if it's even well-defined. However, if ordering is important you can control it with a RuleChain which allows you to define an order on how rules are applied when you have multiple rules in a test case.

From the Javadoc...

@Rule
public RuleChain chain = RuleChain
                           .outerRule(new LoggingRule("outer rule")
                           .around(new LoggingRule("middle rule")
                           .around(new LoggingRule("inner rule");
Fruitarian answered 13/2, 2016 at 13:1 Comment(5)
Thanks. This is what I am looking for!Kiona
" I'm not sure what the default ordering of rule application is, or if it's even well-defined." I have a hypothesis that the ordering is defined by the order of declaration within the class. I have not yet tested this, though.Kiona
@Kiona that may be. I'm just not sure if the JLS or JDK provides a guarantee on what order fields are returned in from a reflective call compared to the order that they're declared in the source. I certainly wouldn't want to depend on it for testing to work.Fruitarian
That's a good point. Of course, JUnit itself might define an execution order. I'm too lazy to research it right now, though.Kiona
@Kiona Apparently not, see junit.org/junit4/javadoc/4.12/org/junit/Rule.html: > However, if there are multiple fields (or methods) they will be applied in an order that depends on your JVM's implementation of the reflection API, which is undefined, in general.Marceau
B
5

RuleChain is deprecated and since 4.13 you can make use of order parameter in Rule.

org.junit.Rule annotation has a parameter "order" which you can use to order the Rules in one file.

check the doc in the link below

Rule.java

Byronbyrum answered 11/6, 2019 at 11:42 Comment(0)
S
0

If you're using JUnit for your tests, which I personally recommend, it's not recommended to have multiple rules in the same file, because a Rule is a unit of your test, and as you're doing unit tests, you should have just one Rule per file.

If you need to create some sort of data before you run your tests you should use the @Before and then load the necessary information. More on this can be found here: http://junit.sourceforge.net/javadoc/org/junit/Before.html

If you have to load the same data in multiple classes, I would recommend you to create a class with your logic, extend that class in your test class and then create a method annotated with @Before an call your super class method.

Hope that helps

Serf answered 12/2, 2016 at 23:33 Comment(12)
These aren't really unit tests. They are more functional or integration tests. I'm still using JUnit since Android has tools for instrumentation.Kiona
I see, but is it really necessary to have more than one rule inside of your class? Because usually, you would write separate test files for each activitySerf
Also, there are no asserts in my TestRule. I don't understand how your link to the question about multiple asserts is related. I seem to be confused about the uses of test rules. My understanding is that they provide an alternative to the old setUp() and tearDown() methods. At least that is the way I am using them.Kiona
To summarize, the Android API provides a TestRule to launch an app. I want to add some configuration before certain tests run.Kiona
I guess this is what you're looking for: junit.sourceforge.net/javadoc/org/junit/Before.htmlSerf
See if this is gonna help you and tell me if it does, then I'll update my question with this link so that it can help more peopleSerf
The problem is that I need the same @Before method run by several different test classes. I can use that in a superclass, but then I still have the same inheritance hierarchy. I am learning about test rules and wanted to implement the same logic using a rule.Kiona
I can see what your problem is. Maybe the best solution would be to create a class with your logic (or copy it just as you said) extend that class in your test class and then create a method annotated with @Before clause and inside of this method call your inherited method. I guess that would be the best aproach. What do you think?Serf
That certainly will work. Thanks for the suggestion.Kiona
You're welcome. Do you think my original answer was useful or should I delete it? I'm knew to this, so its always good to ask in order to make content as helpful as possibleSerf
I don't think your original answer really addressed my question. That's probably because my original question wasn't entirely clear.Kiona
Rather than deleting, perhaps you can edit it to include the information from the comments. Then we can clean these up.Kiona

© 2022 - 2024 — McMap. All rights reserved.