Skip to content

Yet another programming solutions log

Sample bits from programming for the future generations.

Technologies Technologies
  • Algorithms and Data Structures
  • Java Tutorials
  • JUnit Tutorial
  • MongoDB Tutorial
  • Quartz Scheduler Tutorial
  • Spock Framework Tutorial
  • Spring Framework
  • Bash Tutorial
  • Clojure Tutorial
  • Design Patterns
  • Developer’s Tools
  • Productivity
  • About
Expand Search Form

JUnit Parameterized tests

farenda 2016-01-05 0

JUnit Parameterized Tests are JUnit’s way to execute one test multiple times, but with different data sets. This is commonly known as data-driven testing.

Basically such test classes are executed many times, but using series of data. To do that we have to do a few things:

  • run test class with special Test Runner: org.junit.runners.Parameterized
  • create public static void method that will return a collection of tables, which are sets of data
  • annotate data factory method with @Parameterized annotation to let know JUnit which one is it
  • create a constructor matching number of data items in one data set table (alternatively you can make fields public and annotate them with @Parameter to inject dataset value).

It may look complicated, but it is not. Just look at the examples.

If you are familiar with Spock Framework most probably you have applied that using incredibly cool where blocks.

JUnit Parameterized Test Example

In the first example we’re going to use the constructor approach. Each set of data (table in the collection) consists of three values: a, b, and result. JUnit will instantiate MinimalNumberFinderTest as many times as there the collection size – 3 in this case – and will pass through the constructor appropriate values. We assign them to fields and use in the test.
Note that name attribute of @Parameters annotation is optional and is used to set readable test name – strongly encouraged! :-)

package com.farenda.junit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import java.util.Arrays;
import java.util.Collection;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

@RunWith(Parameterized.class)
public class MinimalNumberFinderTest {

    // with "name" to have readable test name
    @Parameters(name = "minimum of {0} and {1} is {2}")
    public static Collection<Object[]> prepareTestData() {
        return Arrays.asList(new Integer[][] {
                // a, b, result
                {1,   2,  1},
                {23, 12, 12},
                {-7, -9, -9}
        });
    }

    private int a;
    private int b;
    private int result;

    public MinimalNumberFinderTest(int a, int b, int result) {
        this.a = a;
        this.b = b;
        this.result = result;
    }

    @Test
    public void shouldFindMinValue() {
        assertThat(Math.min(a, b), equalTo(result));
    }
}

In the next example we use @Parameter annotation instead of test class constructor. As in the previous example JUnit will instantiate the test class as many times as the size of dataset collection, but instead of passing the data through the constructor it will set annotated fields. Note that the fields must be public and annotation takes table index as parameter to inject correct value from dataset – we’ve skipped the parameter for the first field, because the default value is 0 anyway.

package com.farenda.junit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.util.Arrays;
import java.util.Collection;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

@RunWith(Parameterized.class)
public class MaximumNumberFinderTest {

    @Parameters(name = "maximum of {0} and {1} is {2}")
    public static Collection<Object[]> prepareTestData() {
        return Arrays.asList(new Integer[][] {
              // a,   b,  result
                {1,   2,  2},
                {23, 12, 23},
                {-7, -9, -7}
        });
    }

    @Parameter
    public int a;

    @Parameter(1)
    public int b;

    @Parameter(2)
    public int result;

    @Test
    public void shouldFindMaxValue() {
        assertThat(Math.max(a, b), equalTo(result));
    }
}

How pros do it

In the following test from Spring WebSockets you can see that JUnit Parameterized Tests are not constrained only to numbers, as can be seen in many simple examples, but to any objects:

/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.socket.config.annotation;

import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.AbstractWebSocketIntegrationTests;
import org.springframework.web.socket.JettyWebSocketTestServer;
import org.springframework.web.socket.TomcatWebSocketTestServer;
import org.springframework.web.socket.UndertowTestServer;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.client.jetty.JettyWebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import org.springframework.web.socket.server.HandshakeHandler;
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;

import static org.junit.Assert.*;

/**
 * Integration tests for WebSocket Java server-side configuration.
 *
 * @author Rossen Stoyanchev
 */
@RunWith(Parameterized.class)
public class WebSocketConfigurationTests extends AbstractWebSocketIntegrationTests {

        @Parameters(name = "server [{0}], client [{1}]")
        public static Iterable<Object[]> arguments() {
                return Arrays.asList(new Object[][] {
                                {new JettyWebSocketTestServer(), new JettyWebSocketClient()},
                                {new TomcatWebSocketTestServer(), new StandardWebSocketClient()},
                                {new UndertowTestServer(), new StandardWebSocketClient()}
                });
        }


        @Override
        protected Class<?>[] getAnnotatedConfigClasses() {
                return new Class<?>[] { TestConfig.class };
        }

        @Test
        public void registerWebSocketHandler() throws Exception {
                WebSocketSession session = this.webSocketClient.doHandshake(
                                new AbstractWebSocketHandler() {}, getWsBaseUrl() + "/ws").get();

                TestHandler serverHandler = this.wac.getBean(TestHandler.class);
                assertTrue(serverHandler.connectLatch.await(2, TimeUnit.SECONDS));

                session.close();
        }

        @Test
        public void registerWebSocketHandlerWithSockJS() throws Exception {
                WebSocketSession session = this.webSocketClient.doHandshake(
                                new AbstractWebSocketHandler() {}, getWsBaseUrl() + "/sockjs/websocket").get();

                TestHandler serverHandler = this.wac.getBean(TestHandler.class);
                assertTrue(serverHandler.connectLatch.await(2, TimeUnit.SECONDS));

                session.close();
        }


        @Configuration
        @EnableWebSocket
        static class TestConfig implements WebSocketConfigurer {

                @Autowired
                private HandshakeHandler handshakeHandler; // can't rely on classpath for server detection

                @Override
                public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
                        registry.addHandler(serverHandler(), "/ws")
                                .setHandshakeHandler(this.handshakeHandler);
                        registry.addHandler(serverHandler(), "/sockjs").withSockJS()
                                .setTransportHandlerOverrides(new WebSocketTransportHandler(this.handshakeHandler));
                }

                @Bean
                public TestHandler serverHandler() {
                        return new TestHandler();
                }
        }

        private static class TestHandler extends AbstractWebSocketHandler {

                private CountDownLatch connectLatch = new CountDownLatch(1);

                @Override
                public void afterConnectionEstablished(WebSocketSession session) throws Exception {
                        this.connectLatch.countDown();
                }
        }

}
Share with the World!
Categories JUnit Tags java, junit, unit-tests
Previous: JUnit Test Suites
Next: JUnit Assume – execute tests conditionally

Recent Posts

  • Java 8 Date Time concepts
  • Maven dependency to local JAR
  • Caesar cipher in Java
  • Java casting trick
  • Java 8 flatMap practical example
  • Linked List – remove element
  • Linked List – insert element at position
  • Linked List add element at the end
  • Create Java Streams
  • Floyd Cycle detection in Java

Pages

  • About Farenda
  • Algorithms and Data Structures
  • Bash Tutorial
  • Bean Validation Tutorial
  • Clojure Tutorial
  • Design Patterns
  • Java 8 Streams and Lambda Expressions Tutorial
  • Java Basics Tutorial
  • Java Collections Tutorial
  • Java Concurrency Tutorial
  • Java IO Tutorial
  • Java Tutorials
  • Java Util Tutorial
  • Java XML Tutorial
  • JUnit Tutorial
  • MongoDB Tutorial
  • Quartz Scheduler Tutorial
  • Software Developer’s Tools
  • Spock Framework Tutorial
  • Spring Framework

Tags

algorithms bash bean-validation books clojure design-patterns embedmongo exercises git gof gradle groovy hateoas hsqldb i18n java java-basics java-collections java-concurrency java-io java-lang java-time java-util java-xml java8 java8-files junit linux lists log4j logging maven mongodb performance quartz refactoring regex rest slf4j solid spring spring-boot spring-core sql unit-tests

Yet another programming solutions log © 2021

sponsored