JUnit parameter in #Rule #Before and #After - java

I need an advice on how the following snippet can be implemented in all test methods.
#Test
public void testCatalogItemUpdate() {
String correlationId = getCorrelation();
try {
parallel().actions(
//use correlationId
//invoke test scenario
//assert results
);
} finally {
print(correlationId);
}
}
I read about #Rule and #Before and #After annotations.

I can not comment as i don't have enough points so i tried to give the solution with my understanding. So please clarify one thing that you added the comments with in parameter section like below
parallel().action(/*test scenario and assert results are here*/);
Any specific reason for it?
Here is the code snippet. Please check if it helps
private String correlationId;
#Before
public void beforeEachTest(){
correlationId = getCorrelation();
parallel().actions(correlationId);
}
#Test
public void testCatalogItemUpdate(){
//Execute test scenario using correlationId
//Assert results
}
#After
public void afterEachTest(){
print(correlationId);
}

If you need to perform those actions either at the beginning of test or at the end of it, you may try to use those BeforeTest or AfterTest components. I'm not sure if you can call Citrus tests within those sections, but you can try. Here is an example of usage of before test (you need to add it to citrus-context file):
<citrus:before-test id="defaultBeforeTest">
<citrus:actions>
<citrus-test:java class="<class path and class name to be here" >
<citrus-test:method name="<method name>" >
<citrus-test:argument>${<if any variable should be passed>}</citrus-test:argument>
<citrus-test:argument>1</citrus-test:argument>
</citrus-test:method>
</citrus-test:java>
<!-- access to Citrus method -->
<citrus-test:purge-channel>
<citrus-test:channel name="<server_name>.inbound"/>
</citrus-test:purge-channel>
</citrus:actions>
</citrus:before-test>
You may also look at the Templates in Citrus (http://www.citrusframework.org/reference/html/templates.html), especially if you need to run that code in the middle of your test case.

You can use the BeforeTestSupport classes in Citrus
You should extend the BeforeTestSupport classes and add these to the Spring application context:
public class MyBeforeTest extends TestDesignerBeforeTestSupport {
#Override
public void beforeTest(TestDesigner designer) {
designer.echo("This action should be executed before suite");
}
}
<bean id="myBeforeTest" class="my.company.citrus.MyBeforeTest"/>
The beforeTest method is provided with the test designer instance which is then capable to receive the Java DSL calls in Citrus. Of course you can also use the test runner alternative with respective base TestRunnerBeforeTestSupport class.

Related

Run specific unit test according to condition

I have a test class containing test cases for say blue and non-blue devices. If the parameter isBlue is set then it should run only those test case that have say the #Blue annotation. I am not sure how to implement this specific annotation that will achieve this functionality.
public class TestClass {
boolean isBlue = false;
#Before
public void setUp () {
isBlue = MyApplication.instance().isBlue();
}
#Test
public void testA () { ... }
#Test #Blue
public void testB() { ... }
}
In this example if isBlue is true then it should only run testB() otherwise it should run all test cases
Take a look at JUnit runners. Nice explanation of runners
You can create your own runner which will extend on BlockJUnit4ClassRunner.
You can override
#Override
protected List<FrameworkMethod> getChildren() {
// scan test class for methonds annotated with #Test
}
To additionally filter by methods that have your custom annotation set, and your property in the application is set as well.
I think you are on the wrong path.
You want your test cases to help identifying problems; and assist you in fixing them. Anything that "distracts" you from that purpose reduces the values of your unit tests.
Thus: don't put tests that have really "different" scope into the same test class. Especially from the point of view: how would you control what "MyApplication.instance()" would return? That sounds like a problem in itself.
Meaning: you want to have two independent tests; and those don't rely on some "static" object telling them something. They test what is in their scope; nothing else.
By using jUnit Assume
#Test
public void testA () {
assumeTrue(MyApplication.instance().isBlue());
...
}
A failing assumption in a #Before or #BeforeClass method will have the same effect as a failing assumption in each #Test method of the class.

testNG annotation which would equal to "finally" in java?

i don't know if my question was clear, but i am using testNG and i have this:
#Test
public void passengerServiceTest() {
...
}
#AfterTest
public void deleteCreatedPassenger() {
...
}
I want to execute my deleteCreatedPassenger() method after passengerServiceTest, also, i want that in case of deleteCreatedPassenger fails, passengerServiceTest fails too, in other words, i want that both of them be the same test, so if one them fails, test fails.
So i tried with the annotations #AfterTest, #AfterMethod, #AfterClass and all make two tests as "separated" tests.
Do you know how to do this? Regards
You don't need annotations to achieve this, since it's exactly what the finally block is intended for:
#Test
public void passengerServiceTest() {
try {
//test code
} finally {
deleteCreatedPassenger();
}
}
public void deleteCreatedPassenger() {
...
}
If the delete throws an exception then your service test fails.
Annotations are useful in certain scenarios, you shouldn't aim to use them over core language constructs.
alwaysRun
https://testng.org/doc/documentation-main.html
Ex:
#AfterTest(alwaysRun = true)
public void deleteOldValuesFromDatabase() {
...
}
Docs say that this will cause the method to run "even if one or more methods invoked previously failed or was skipped"

JUNIT : run setup only once for a large number of test classes

I have a class, which I use as a basis for my unit tests. In this class I initialize the whole environment for my tests, setting up database mappings, enter a number of database records across multiple tables, etc. That class has a method with a #BeforeClass annotation which does the initialization. Next thing, I extend that class with specific classes in which I have #Test methods.
My question is, since the before class is exactly the same for all these test classes, how can I ensure that they are run only once for all the tests.
One simple solution is that I could keep all the tests in one class. However, the number of tests is huge, also they are categorised based on functional heads. So they are located in different classes. However since they need the exact same setup, they inherit the #BeforeClass. As a result the whole setup is done at least once per test class, taking much more time in total than I would prefer.
I could, though, put them all in various subpackages under one package, hence if there is a way, how I can run set up once for all the tests within that package, it would be great.
With JUnit4 test suite you can do something like this :
#RunWith(Suite.class)
#Suite.SuiteClasses({ Test1IT.class, Test2IT.class })
public class IntegrationTestSuite
{
#BeforeClass
public static void setUp()
{
System.out.println("Runs before all tests in the annotation above.");
}
#AfterClass
public static void tearDown()
{
System.out.println("Runs after all tests in the annotation above.");
}
}
Then you run this class as you would run a normal test class and it will run all of your tests.
JUnit doesn't support this, you will have to use the standard Java work-arounds for singletons: Move the common setup code into a static code block and then call an empty method in this class:
static {
...init code here...
}
public static void init() {} // Empty method to trigger the execution of the block above
Make sure that all tests call init(), for example my putting it into a #BeforeClass method. Or put the static code block into a shared base class.
Alternatively, use a global variable:
private static boolean initialize = true;
public static void init() {
if(!initialize) return;
initialize = false;
...init code here...
}
Create one base class for all tests:
public class BaseTest {
static{
/*** init code here ***/
}
}
and every test should inherit from it:
public class SomeTest extends BaseTest {
}
You can make one BaseTest class with a #BeforeClass method, then have all the other tests inherit from it. This way, when each test object is constructed, #BeforeClass gets executed.
Also avoid executing it just once for all the test suite, since all the test cases should be independent. #BeforeClass should execute only once each test case, not test suite.
If you can tolerate adding spring-test to your project, or you are using it already, then a good approach is to use the technique described here: How to load DBUnit test data once per case with Spring Test
Not sure if anyone still is using JUnit and trying to fix it without using Spring Runner (aka no spring integration). TestNG has this feature. But here is a JUnit based solution.
Create a RunOnce per thread operation like so. This maintains a list of classes for which the operation has run.
public class RunOnceOperation {
private static final ThreadLocal t = new ThreadLocal();
public void run(Function f) {
if (t.get() == null) {
t.set(Arrays.asList(getClass()));
f.apply(0);
} else {
if (!((List) t.get()).contains(getClass())) {
((List) t.get()).add(getClass());
f.apply(0);
}
}
}
}
Back in your unit test
#Before
public beforeTest() {
operation.run(new Function<Integer, Void>() {
#Override
public Void apply(Integer t) {
checkBeanProperties();
return null;
}
});
}
private void checkBeanProperties() {
//I only want to check this once per class.
//Also my bean check needs instance of the class and can't be static.
}
My function interface is like this:
interface Function<I,O> {
O apply(I i);
}
When you use this way, you can perform operations once per class using ThreadLocal.

Conditionally ignoring tests in JUnit 4

OK, so the #Ignore annotation is good for marking that a test case shouldn't be run.
However, sometimes I want to ignore a test based on runtime information. An example might be if I have a concurrency test that needs to be run on a machine with a certain number of cores. If this test were run on a uniprocessor machine, I don't think it would be correct to just pass the test (since it hasn't been run), and it certainly wouldn't be right to fail the test and break the build.
So I want to be able to ignore tests at runtime, as this seems like the right outcome (since the test framework will allow the build to pass but record that the tests weren't run). I'm fairly sure that the annotation won't give me this flexibility, and suspect that I'll need to manually create the test suite for the class in question. However, the documentation doesn't mention anything about this and looking through the API it's also not clear how this would be done programmatically (i.e. how do I programatically create an instance of Test or similar that is equivalent to that created by the #Ignore annotation?).
If anyone has done something similar in the past, or has a bright idea of how else I could go about this, I'd be happy to hear about it.
The JUnit way is to do this at run-time is org.junit.Assume.
#Before
public void beforeMethod() {
org.junit.Assume.assumeTrue(someCondition());
// rest of setup.
}
You can do it in a #Before method or in the test itself, but not in an #After method. If you do it in the test itself, your #Before method will get run. You can also do it within #BeforeClass to prevent class initialization.
An assumption failure causes the test to be ignored.
Edit: To compare with the #RunIf annotation from junit-ext, their sample code would look like this:
#Test
public void calculateTotalSalary() {
assumeThat(Database.connect(), is(notNull()));
//test code below.
}
Not to mention that it is much easier to capture and use the connection from the Database.connect() method this way.
You should checkout Junit-ext project. They have RunIf annotation that performs conditional tests, like:
#Test
#RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
//your code there
}
class DatabaseIsConnected implements Checker {
public boolean satisify() {
return Database.connect() != null;
}
}
[Code sample taken from their tutorial]
In JUnit 4, another option for you may be to create an annotation to denote that the test needs to meet your custom criteria, then extend the default runner with your own and using reflection, base your decision on the custom criteria. It may look something like this:
public class CustomRunner extends BlockJUnit4ClassRunner {
public CTRunner(Class<?> klass) throws initializationError {
super(klass);
}
#Override
protected boolean isIgnored(FrameworkMethod child) {
if(shouldIgnore()) {
return true;
}
return super.isIgnored(child);
}
private boolean shouldIgnore(class) {
/* some custom criteria */
}
}
Additionally to the answer of #tkruse and #Yishai:
I do this way to conditionally skip test methods especially for Parameterized tests, if a test method should only run for some test data records.
public class MyTest {
// get current test method
#Rule public TestName testName = new TestName();
#Before
public void setUp() {
org.junit.Assume.assumeTrue(new Function<String, Boolean>() {
#Override
public Boolean apply(String testMethod) {
if (testMethod.startsWith("testMyMethod")) {
return <some condition>;
}
return true;
}
}.apply(testName.getMethodName()));
... continue setup ...
}
}
A quick note: Assume.assumeTrue(condition) ignores rest of the steps but passes the test.
To fail the test, use org.junit.Assert.fail() inside the conditional statement. Works same like Assume.assumeTrue() but fails the test.

JUnit: #Before only for some test methods?

I have some common set up code that I've factored out to a method marked with #Before. However, it is not necessary for all this code to run for every single test. Is there a way to mark it so the #Before method only runs before certain tests?
Just move out the tests that don't need the setup code into a separate test class. If you have some other code common to the tests that would be helpful to keep, move that out into a helper class.
#Nested + #BeforeEach
Totally agree with the point of moving the related code to an inner class. So here what I have done.
Create an inner class inside your test class
Annotate the inner class with #Nested
Move all the test methods you want to use in the inner class
Write the init code inside the inner class and annotate it with #BeforeEach
Here is the code:
class Testing {
#Test
public void testextmethod1() {
System.out.println("test ext method 1");
}
#Nested
class TestNest{
#BeforeEach
public void init() {
System.out.println("Init");
}
#Test
public void testmethod1() {
System.out.println("This is method 1");
}
#Test
public void testmethod2() {
System.out.println("This is method 2");
}
#Test
public void testmethod3() {
System.out.println("This is method 3");
}
}
#Test
public void testextmethod2() {
System.out.println("test ext method 2");
}
}
Here is the output
test ext method 1
test ext method 2
Init
This is method 1
Init
This is method 2
Init
This is method 3
Note: I am not sure if this is supported in Junit4. I am doing this in JUnit5
It is possible to achieve also via Assume from JUnit. And then you can check the method name for which you want to process #Before.
public class MyTest {
#Rule
public TestName testName = new TestName();
#Before
public void setUp() {
assumeTrue(testName.getMethodName().equals("myMethodName"));
// setup follows
}
}
Check the topic for more insights about #Rule.
Now that it's 2023, I'd recommend sticking with JUnit 5.x
I'd also say that this is probably a micro-optimization. I would not go to the effort until I measured my test time and saw that running the code when it wasn't necessary added a significant amount of time.
Not sure about #Before, but I recently came up with a strategy for #After block to run selectively. The implementation was straight forward. I have some flags set to default values as part of the test class. They are reset to default values in #Before class. In the class I need to do things specific to a flag, I set those flags & in #After I check for flag values to do the respective jobs.
JUnit 4.12 provide Enclosed Runner like
#RunWith(Enclosed.class)
public class GlobalTest{
#RunWith(MockitoJUnitRunner.class)
public class InnerTest{
}
}

Categories

Resources