How to Implicitly Infer the Type of Fail Method in JUnit 5
- Create a Kotlin Project and Add Dependencies
-
Not enough information to infer type variable V
-
Infer the Type of the
fail()
Method Explicitly -
Use the
fail()
Method With Lambda Expressions -
Implicitly Inferring the Type of the
fail()
Method - Conclusion
Testing is an important step in the development of any application as it helps detect bugs early in the development stage, improves the application’s performance, and reduces the cost of development.
Suppose testing is a critical process in an application. In that case, it’s recommended to use the test-driven development (TDD) approach, which starts implementing any feature with failing tests, followed by the actual code that finally makes the test pass.
Different types of testing can be done in an application, including unit testing, integration testing, functional testing, and others. This tutorial will teach how to implicitly infer the type of the fail()
method used in the unit testing stage with JUnit 5.
Create a Kotlin Project and Add Dependencies
Open IntelliJ development environment and select File
> New
> Project
. On the window that opens, enter the project Name
as kotlin-testing
, select Kotlin
on the Language
section, and select Gradle
on the Build system
section.
Press the Create
button to generate the project.
Open the build.gradle
file and ensure you have the junit-jupiter-api
dependency as shown below. This dependency provides us with the APIs we use to test our code.
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
testImplementation 'org.jetbrains.kotlin:kotlin-test'
}
Create a Main.kt
file under the src/main/kotlin
folder and copy and paste the following code into the file.
class Student(
var id: Int,
var studentName: String?,
var studentIDCard: String?){
override fun toString(): String {
return "student name: $studentName, ID card: $studentIDCard"
}
}
fun getStudents(): List<Student>{
return listOf(
Student(1,"john doe","CSO12022"),
Student(2,"mary public","CS022022"),
Student(3,"elon mask","S032022")
);
}
In the above code, we have created a list that contains student
objects, and we will use this list to do the testing.
Not enough information to infer type variable V
Create a Main.kt
file under the src/test/kotlin
folder and copy and paste the following code into the file.
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.fail
class TestStudents{
private val students: List<Student> = getStudents();
@Test
fun checkEmptyClass(){
if (students.isNotEmpty()){
fail("The class is not empty")
}
}
}
In this code, we have created a test with the name checkEmptyClass()
that uses the list we created in the previous section to check whether it is empty. If the list is not empty, we call the fail()
method and pass an error message as the method’s argument.
Note that we use the static method fail()
of the Assertions
class. The fully qualified name of the class is org.junit.jupiter.api.Assertions
.
When using the fail()
method from this class, the compiler shows a warning with the message Not enough information to infer type variable V
because the method is generic and we have not provided any type parameters.
Infer the Type of the fail()
Method Explicitly
The easiest approach that first comes to mind is explicitly providing the type parameters to appease the compiler, as shown in the following code.
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.fail
class TestStudents{
private val students: List<Student> = getStudents();
@Test
fun checkEmptyClass(){
if (students.isNotEmpty()){
fail<String>("The class is not empty")
}
}
}
Note that the reason we used the statement to appease the compiler is that the type is never returned because the exception org.opentest4j.AssertionFailedError
is thrown before reaching the return statement.
In simple terms, we provide a generic parameter that is useless in our code. The next section shows how we can call this method without explicitly providing the generic parameters.
Run this test and ensure it fails with the following message.
The class is not empty
org.opentest4j.AssertionFailedError: The class is not empty
Use the fail()
Method With Lambda Expressions
Comment on the example above and copy and paste the following code into the Main.kt
file under the src/test/kotlin
folder.
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.fail
class TestStudents{
private val students: List<Student> = getStudents();
@Test
fun findInvalidStudentIDCard(){
students.forEach { student: Student ->
if (student.studentIDCard?.startsWith("CS") == true){
println(student)
}else{
fail("$student has an invalid id");
}
}
}
}
In this example, we have created a test named findInvalidStudentIDCard()
that iterates through the student
list, logs the students with a valid card number, and calls the fail()
method if the card number is invalid.
We have used the forEach()
method that accepts one parameter and does not return any value. This is usually referred to as a Consumer
.
When working with lambda expressions, we do not need to infer the type explicitly, as the compiler can infer the type from the Consumer
passed to the method.
In this code, the compiler does not show any compile time errors. Run this test and ensure the output is as shown below.
student name: john doe, ID card: CSO12022
student name: mary public, ID card: CS022022
student name: elon mask, ID card: S032022 has an invalid id
org.opentest4j.AssertionFailedError: student name: elon mask, ID card: S032022 has an invalid id
Implicitly Inferring the Type of the fail()
Method
Comment on the example above and copy and paste the following code into the Main.kt
file under the src/test/kotlin
folder.
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.fail
class TestStudents{
private val students: List<Student> = getStudents();
@Test
fun checkClassSize(){
if (students.count() < 5){
fail("The class is not full")
}
}
}
In this example, we have created a test named checkClassSize()
that counts the number of student objects in the list, and if the count is less than 5
, we call the fail()
method and pass an error message as the argument of the method.
Note that the fail()
method in this example is not the generic method from the Assertions
class. The fail()
method in this example comes from the org.junit.jupiter.api
package, which is not generic.
Since the method is not generic, we do not need to pass any parameters. Run this test and ensure the output is as shown below.
The class is not full
org.opentest4j.AssertionFailedError: The class is not full
Conclusion
In this tutorial, we have learned what causes the compile time error when using the fail()
method. We have learned how we can explicitly infer the type of the method to avoid this warning.
In the last two sections, we have learned how the type is implicitly inferred when using lambda expressions and how we avoid inferring the type by using a method that is not generic.
David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.
LinkedIn GitHub