Integration of Karate API with JUnit 5

  

Integrating JUnit 5 with Karate API Testing framework allows you to run your BDD-style .feature files as part of your unit/integration test suite using the JUnit 5 engine. Below is a detailed guide and working code example.


Step-by-Step Integration: JUnit 5 + Karate API


1. Add Dependencies in pom.xml



<dependencies>
    <!-- Karate core -->
    <dependency>
        <groupId>com.intuit.karate</groupId>
        <artifactId>karate-junit5</artifactId>
        <version>1.4.1</version> <!-- or latest -->
        <scope>test</scope>
    </dependency>

    <!-- Optional: For HTML Reporting -->
    <dependency>
        <groupId>net.masterthought</groupId>
        <artifactId>cucumber-reporting</artifactId>
        <version>5.7.0</version>
    </dependency>
</dependencies>




2. Create Karate Test Feature File

src/test/resources/examples/sample.feature


Feature: Sample Karate Test

  Scenario: Get Request Test
    Given url 'https://jsonplaceholder.typicode.com/posts/1'
    When method get
    Then status 200
    And match response.id == 1




3. Create JUnit 5 Test Runner

src/test/java/examples/RunKarateTest.java


package examples;

import com.intuit.karate.junit5.Karate;

class RunKarateTest {

    @Karate.Test
    Karate testAll() {
        // Run all feature files in the package `examples`
        return Karate.run().relativeTo(getClass());
    }

    @Karate.Test
    Karate testSpecificFeature() {
        // Run a specific feature file
        return Karate.run("sample").relativeTo(getClass());
    }
}



4. Run Tests

You can run the tests:

  • From IDE (IntelliJ / Eclipse) — right-click RunKarateTest → Run.

  • From Maven:


mvn test


5. View Reports

Karate generates HTML reports by default at:

target/karate-reports/karate-summary.html

Integration of Selenium, Cucumber, and JUnit

  

To integrate SeleniumCucumber, and JUnit, you can build a Behavior Driven Development (BDD) test framework that allows you to define test scenarios in Gherkin (plain English), implement those steps in Java (using Selenium for UI interactions), and execute them using JUnit.


Components Overview:


ComponentRole
Selenium WebDriverAutomates browser actions
CucumberProvides BDD support via .feature files
JUnitExecutes the test suite (test runner)




Below are the steps to integrate Selenium, Cucumber and JUnit


1. Maven Dependencies


<dependencies>
    <!-- Selenium -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.19.1</version>
    </dependency>

    <!-- Cucumber -->
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>7.14.0</version>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>7.14.0</version>
        <scope>test</scope>
    </dependency>

    <!-- JUnit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>




2. Feature File 


Feature: Google Search Functionality

  Scenario: Search for a keyword on Google
    Given I open the Chrome browser
    When I open "https://www.google.com"
    And I search for "Cucumber BDD"
    Then I should see the results page




3. Step Definition file


package stepDefinitions;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.en.*;

import static org.junit.Assert.*;

public class GoogleSearchSteps {
    WebDriver driver;

    @Given("I open the Chrome browser")
    public void i_open_the_chrome_browser() {
        System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
        driver = new ChromeDriver();
    }

    @When("I open {string}")
    public void i_open(String url) {
        driver.get(url);
    }

    @When("I search for {string}")
    public void i_search_for(String query) {
        WebElement searchBox = driver.findElement(By.name("q"));
        searchBox.sendKeys(query);
        searchBox.submit();
    }

    @Then("I should see the results page")
    public void i_should_see_the_results_page() {
        assertTrue(driver.getTitle().toLowerCase().contains("cucumber bdd"));
        driver.quit();
    }
}




4. JUnit Test Runner


package runners;

import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/features",
    glue = {"stepDefinitions"},
    plugin = { "pretty", "html:target/cucumber-reports" },
    monochrome = true
)
public class TestRunner {
}


How to Run the Tests

Right-click on TestRunner.java > Run As > JUnit Test
or
Use the Maven command:

mvn test


 Output

  • Browser opens Google

  • Types the query and submits

  • Assertion is done on the title

  • Generates HTML report in: target/cucumber-reports/index.html

What is TDD and how to use JUnit as TDD

  

What is TDD (Test-Driven Development)?

Test-Driven Development (TDD) is a software development methodology where you write tests before writing actual code. The main goal of TDD is to improve the design, quality, and maintainability of code.


TDD Workflow (The Red-Green-Refactor Cycle)

  1. Red – Write a failing test

    • Write a test case for the desired functionality before writing the code.

    • Since the code doesn’t exist yet, the test will fail.

  2. Green – Make the test pass

    • Write the minimal amount of code needed to make the test pass.

    • Focus only on passing the test.

  3. Refactor – Improve the code

    • Clean up the code while ensuring that all tests still pass.

    • Improve readability, remove duplication, optimize logic.

This cycle continues for each new piece of functionality.


Benefits of TDD

  • Forces requirement clarity before implementation.

  • Results in better design and decoupled components.

  • Reduces bugs due to automated tests.

  • Makes refactoring safe (you have tests as safety net).

  • Improves developer confidence and code coverage.


How to Use JUnit for TDD in Java

JUnit is a widely used testing framework in Java, perfect for TDD.


TDD Example with JUnit

Let’s develop a method to check if a number is prime using TDD.


Step 1: Write Failing Test


import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

public class PrimeUtilTest {

    @Test
    public void testIsPrime() {
        assertTrue(PrimeUtil.isPrime(5));  // test will fail: isPrime not implemented
        assertFalse(PrimeUtil.isPrime(4));
        assertTrue(PrimeUtil.isPrime(2));
    }
}




Step 2: Write Minimal Code to Pass


public class PrimeUtil {

    public static boolean isPrime(int number) {
        if (number <= 1) return false;
        for (int i = 2; i <= Math.sqrt(number); i++) {
            if (number % i == 0) return false;
        }
        return true;
    }
}



Step 3: Refactor if Needed

  • You can extract logic, rename variables, or make code cleaner.

  • No need to change behavior; just improve structure.



Best Practices When Using JUnit for TDD

  • Use descriptive names for tests (testAddTwoNumbersReturnsSum)

  • Start simple; avoid over-engineering.

  • Test both positive and negative cases.

  • Use tools like Maven or Gradle for test automation.

  • Keep test methods independent and isolated.




At a glance:


StepActionStatus
RedWrite test that failsDone
GreenWrite code to make the test passDone
RefactorClean up code without breaking the testOptional

Parameterization in JUnit

  

What is Parameterization in JUnit?

Parameterization in JUnit allows you to run the same test multiple times with different inputs. This is useful when you want to test a method using a variety of inputs and expected outputs without duplicating test code.

JUnit provides two main ways to do parameterized testing:

  • In JUnit 4: using @RunWith(Parameterized.class)

  • In JUnit 5: using the @ParameterizedTest annotation from org.junit.jupiter.params



JUnit 4 Parameterized Test

Steps:

  • Annotate the class with @RunWith(Parameterized.class)
  • Create a method annotated with @Parameters to return test data.
  • Define fields to hold parameters.
  • Create a constructor to initialize them.
  • Write your test method using those parameters.


Example:


import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class AdditionTest {

    private int a;
    private int b;
    private int expectedSum;

    // Constructor to initialize parameters
    public AdditionTest(int a, int b, int expectedSum) {
        this.a = a;
        this.b = b;
        this.expectedSum = expectedSum;
    }

    // This method provides test data
    @Parameterized.Parameters
    public static Collection<Object[]> testData() {
        return Arrays.asList(new Object[][] {
            {1, 2, 3},
            {5, 3, 8},
            {10, 15, 25},
            {0, 0, 0}
        });
    }

    @Test
    public void testAddition() {
        assertEquals(expectedSum, a + b);
    }
}




JUnit 5 Parameterized Test

Steps:

  • Add dependency for junit-jupiter-params
  • Use @ParameterizedTest annotation.
  • Use @ValueSource@CsvSource, or @MethodSource to provide values.



Example 1: Using @ValueSource


import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class OddNumberTest {

    @ParameterizedTest
    @ValueSource(ints = {1, 3, 5, 7, 9})
    public void testIsOdd(int number) {
        assertTrue(number % 2 != 0);
    }
}





Example 2: Using @CsvSource


import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class AdditionTest {

    @ParameterizedTest
    @CsvSource({
        "1, 2, 3",
        "5, 3, 8",
        "10, 15, 25"
    })
    void testAddition(int a, int b, int expectedSum) {
        assertEquals(expectedSum, a + b);
    }
}




Comparison:


FeatureJUnit 4JUnit 5
Setup@RunWith(Parameterized.class)@ParameterizedTest
Data source@Parameters (method)@ValueSource, @CsvSource, @MethodSource
Constructor requiredYesNo
External data flexibilityLessMore flexible

Exception Test in JUnit

  

What is Exception Test in JUnit?

In JUnit, an exception test is used to verify that a method throws a specific exception under certain conditions. It's a type of negative test to ensure your code fails gracefully when given invalid inputs or when something unexpected occurs.


Why Use Exception Tests?

Exception tests are useful to:

  • Validate input checks.

  • Ensure robust error handling.

  • Test edge cases and defensive programming logic.


How to Write Exception Tests in JUnit



JUnit 4: Using @Test(expected = Exception.class)


import org.junit.Test;

public class ExceptionTestExample {

    @Test(expected = ArithmeticException.class)
    public void testDivideByZero() {
        int result = 10 / 0;  // This will throw ArithmeticException
    }
}


Explanation:

  • If ArithmeticException is thrown, the test passes.

  • If no exception or a different one is thrown, the test fails.




JUnit 5: Using Assertions.assertThrows()


import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ExceptionTestExample {

    @Test
    void testDivideByZero() {
        assertThrows(ArithmeticException.class, () -> {
            int result = 10 / 0;
        });
    }
}


Explanation:

  • assertThrows() checks whether the given lambda throws the specified exception.

  • It gives more flexibility (example: checking exception message or stack trace).



Example: Custom Exception Test (JUnit 5)


class InvalidAgeException extends RuntimeException {
    public InvalidAgeException(String message) {
        super(message);
    }
}

class Person {
    public void setAge(int age) {
        if (age < 0) {
            throw new InvalidAgeException("Age cannot be negative");
        }
    }
}

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class PersonTest {

    @Test
    void testInvalidAgeException() {
        Person person = new Person();
        Exception exception = assertThrows(InvalidAgeException.class, () -> {
            person.setAge(-5);
        });

        assertEquals("Age cannot be negative", exception.getMessage());
    }
}




At a glance:


FeatureJUnit 4JUnit 5
Exception Test Syntax@Test(expected = Exception.class)assertThrows(Exception.class, () -> {...})
Can check messageNoYes
Recommended for new codeNo, because syntax is oldYes, because of flexibility

Integration of Selenium with JUnit

  

Integrating Selenium with JUnit

JUnit and Selenium are often used together for automated UI testing. JUnit acts as the test runner and assertion framework, while Selenium automates browser actions.


Prerequisites for integration of Selenium with JUnit

  • Java installed
  • Eclipse or IntelliJ IDE
  • Maven or Gradle for dependency management
  • JUnit (JUnit 4 or 5)
  • Selenium WebDriver


Step 1: Maven pom.xml Dependencies


<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>selenium-junit-demo</artifactId>
  <version>1.0</version>
  
  <dependencies>
    <!-- Selenium -->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>4.20.0</version>
    </dependency>

    <!-- JUnit 5 -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.10.2</version>
    </dependency>
  </dependencies>
</project>




Step 2: Basic Selenium + JUnit Test

This code will open google page and verify the title contains 'Google'



import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class GoogleTest {

    private WebDriver driver;

    @BeforeEach
    public void setUp() {
        // Make sure to have chromedriver in your system PATH
        driver = new ChromeDriver();
    }

    @Test
    public void testGoogleTitle() {
        driver.get("https://www.google.com");
        String title = driver.getTitle();
        assertTrue(title.contains("Google"), "Title should contain 'Google'");
    }

    @AfterEach
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}




Explanation


PartDescription
@BeforeEachRuns before each test – initializes WebDriver
@TestYour actual test logic using Selenium
@AfterEachRuns after each test – closes the browser
assertTrueAsserts that the page title contains "Google"


Running the Tests

  • Right-click the class → Run As > JUnit Test in Eclipse/IntelliJ
  • Or via terminal (if using Maven):

mvn test


Best Practices

  • Use Page Object Model (POM) for maintainability

  • Use WebDriverManager to auto-manage browser drivers

  • Prefer JUnit 5 over JUnit 4 for new projects