@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);
	}
}
 
 
 
 
 
 
 
 
 

No comments:
Post a Comment