Monday, 19 July 2021

Junit5: Parameterized Test: MethodResource: Pass complex arguments

@MethodSource annotation is used to pass complex arguments to the test method.

 

Step 1: Create a method that produce stream of arguments.

private static Stream<Arguments> provideEmployeeDetails() {
	return Stream.of(
			Arguments.of(new Employee(1, "Krishna", "Gurram")),
			Arguments.of(new Employee(2, "Gopi", "Battu")), 
			Arguments.of(new Employee(3, "Ram", "Ponnam"))
			);
}

 

Step 2: Specify the method defined in step 1 as method source.

@ParameterizedTest
@MethodSource("provideEmployeeDetails")
void getEmployeeAsStringTest1(Employee emp) {
	String expected = emp.getId() + "," + emp.getFirstName() + "," + emp.getLastName();
	String actual = EmployeeUtil.getEmployeeAsString(emp);

	assertEquals(expected, actual);
}

 

That’s it you are done.

 

You can even pass multiple arguments to a test method using stream of arguments.

private static Stream<Arguments> provideEmployeeInfo() {
	return Stream.of(
			Arguments.of(1, "Krishna", "Gurram"), 
			Arguments.of(2, "Gopi", "Battu"),
			Arguments.of(3, "Ram", "Ponnam")
			);
}

 

@ParameterizedTest
@MethodSource("provideEmployeeInfo")
void getEmployeeAsStringTest2(int id, String firstName, String lastName) {
	Employee emp = new Employee(id, firstName, lastName);
	String expected = emp.getId() + "," + emp.getFirstName() + "," + emp.getLastName();
	String actual = EmployeeUtil.getEmployeeAsString(emp);

	assertEquals(expected, actual);
}

 

Find the below working application.

 

Employee.java

 

package com.sample.app;

public class Employee {

	private int id;
	private String firstName;
	private String lastName;

	public Employee() {

	}

	public Employee(int id, String firstName, String lastName) {
		super();
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

}

 

EmployeeUtil.java

package com.sample.app.util;

import com.sample.app.Employee;

public class EmployeeUtil {

	public static String getEmployeeAsString(Employee emp) {
		if(emp == null) {
			return "none";
		}
		
		return emp.getId()+","+emp.getFirstName()+","+emp.getLastName();
	}
}

MethodSourceDemo1.java

package com.sample.app.util;

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

import java.util.stream.Stream;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import com.sample.app.Employee;

public class MethodSourceDemo1 {

	@ParameterizedTest
	@MethodSource("provideEmployeeDetails")
	void getEmployeeAsStringTest1(Employee emp) {
		String expected = emp.getId() + "," + emp.getFirstName() + "," + emp.getLastName();
		String actual = EmployeeUtil.getEmployeeAsString(emp);

		assertEquals(expected, actual);
	}

	@ParameterizedTest
	@MethodSource("provideEmployeeInfo")
	void getEmployeeAsStringTest2(int id, String firstName, String lastName) {
		Employee emp = new Employee(id, firstName, lastName);
		String expected = emp.getId() + "," + emp.getFirstName() + "," + emp.getLastName();
		String actual = EmployeeUtil.getEmployeeAsString(emp);

		assertEquals(expected, actual);
	}

	private static Stream<Arguments> provideEmployeeDetails() {
		return Stream.of(
				Arguments.of(new Employee(1, "Krishna", "Gurram")),
				Arguments.of(new Employee(2, "Gopi", "Battu")), 
				Arguments.of(new Employee(3, "Ram", "Ponnam"))
				);
	}

	private static Stream<Arguments> provideEmployeeInfo() {
		return Stream.of(
				Arguments.of(1, "Krishna", "Gurram"), 
				Arguments.of(2, "Gopi", "Battu"),
				Arguments.of(3, "Ram", "Ponnam")
				);
	}
}


Run 'MethodSourceDemo1' as junit test, you will see that test methods are executed successfully in junit window.




If a test method takes only one argument, then you can return a Stream of instances of the parameter type.

 

@ParameterizedTest
@MethodSource("stringProvider")
void getLengthTest(String input) {
	int expectedLength = (input == null) ? -1 : input.length();
	int actualLength = getLength(input);

	assertEquals(expectedLength, actualLength);
}

static Stream<String> stringProvider() {
	return Stream.of("apple", "banana", "Carrot", "Mango");
}

 

MethodSourceDemo2.java

package com.sample.app;

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

import java.util.stream.Stream;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class MethodSourceDemo2 {

	private static int getLength(String str) {
		if (str == null) {
			return -1;
		}
		return str.length();
	}

	@ParameterizedTest
	@MethodSource("stringProvider")
	void getLengthTest(String input) {
		int expectedLength = (input == null) ? -1 : input.length();
		int actualLength = getLength(input);

		assertEquals(expectedLength, actualLength);
	}

	static Stream<String> stringProvider() {
		return Stream.of("apple", "banana", "Carrot", "Mango");
	}

}

 

When we don't provide a name for the @MethodSource, JUnit will search for a source method with the same name as the test method.

@ParameterizedTest
@MethodSource
void getLengthTest(String input) {
	int expectedLength = (input == null) ? -1 : input.length();
	int actualLength = getLength(input);

	assertEquals(expectedLength, actualLength);
}

static Stream<String> getLengthTest() {
	return Stream.of("apple", "banana", "Carrot", "Mango");
}

 

MethodSourceDemo3.java

package com.sample.app;

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

import java.util.stream.Stream;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class MethodSourceDemo3 {

	private static int getLength(String str) {
		if (str == null) {
			return -1;
		}
		return str.length();
	}

	@ParameterizedTest
	@MethodSource
	void getLengthTest(String input) {
		int expectedLength = (input == null) ? -1 : input.length();
		int actualLength = getLength(input);

		assertEquals(expectedLength, actualLength);
	}

	static Stream<String> getLengthTest() {
		return Stream.of("apple", "banana", "Carrot", "Mango");
	}

}

 

How to specify external factory method as method source?

An external, static factory method can be referenced by providing its fully qualified method name.

 

@ParameterizedTest
@MethodSource("com.sample.app.util.InputUtil#getStrings")
void getLengthTest(String input) {
	int expectedLength = (input == null) ? -1 : input.length();
	int actualLength = getLength(input);

	assertEquals(expectedLength, actualLength);
}

 

In the above snippet I specified method source as ‘getStrings’ method defined in InputUtil class.

 

InputUtil.java

package com.sample.app.util;

import java.util.stream.Stream;

public class InputUtil {
	public static Stream<String> getStrings() {
		return Stream.of("apple", "banana", "Carrot", "Mango");
	}
}

 

MethodSourceDemo4.java

package com.sample.app;

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

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class MethodSourceDemo4 {
	private static int getLength(String str) {
		if (str == null) {
			return -1;
		}
		return str.length();
	}

	@ParameterizedTest
	@MethodSource("com.sample.app.util.InputUtil#getStrings")
	void getLengthTest(String input) {
		int expectedLength = (input == null) ? -1 : input.length();
		int actualLength = getLength(input);

		assertEquals(expectedLength, actualLength);
	}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment