JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit platform is the core, foundational module of JUnit 5. JUnit Jupiter module is for writing tests and extensions. And JUnit Vintage module is for running JUnit 3 and JUnit 4 tests.Although JUnit 5 is a breakthrough change, writing tests with JUnit 5 is still very similar to JUnit 4 so programmers can quickly use JUnit 5 if they were familiar with previous versions of JUnit.For complete details about JUnit 5 features, I recommend you to look at the official JUnit 5 user guide.
For purpose
| JUnit 5 | JUnit 4 |
Declare a test method
|
@Test |
@Test |
Execute before all test methods |
@BeforeAll |
@BeforeClass
|
Execute before each test method |
@BeforeEach |
@Before
|
Execute after each test method |
@AfterEach |
@After
|
Execute after all test methods |
@AfterAll |
@AfterClass
|
Skip a test method/class |
@Disabled |
@Ignore
|
Tagging and filtering tests |
@Tag |
@Category
|
Run with an extension |
@RunWith |
@ExtendWith
|
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class StandardTests {
@BeforeAll
static void initAll() {
// initializes resources before all test methods
}
@BeforeEach
void init() {
// initializes resources before each test method
}
@Test
void successTest() {
// this test will pass
}
@Test
void failTest() {
fail("this test will fail");
}
@Test
@Disabled
void skippedTest() {
// this test is skipped temporarily
}
@AfterEach
void tearDown() {
// releases resources after each test method
}
@AfterAll
static void tearDownAll() {
// releases resources after all test methods
}
}JUnit 5 changes the annotation names for better reflecting their meanings, and the behavior is the same as JUnit 4. <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.4.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.6.2</version> </dependency>As you can see, the last dependency is for JUnit Jupiter which includes modules for JUnit platform and JUnit Jupiter engine.
package net.codejava;
import javax.persistence.*;
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(length = 64, nullable = false, unique = true)
private String name;
private float price;
public Product() {
}
public Product(String name, float price) {
this(null, name, price);
}
public Product(Integer id) {
this.id = id;
}
public Product(Integer id, String name, float price) {
this.id = id;
this.name = name;
this.price = price;
}
// standard getters and setters
}This is a simple entity class that maps to products table in the database. If you are new to Hibernate, I recommend you to follow this tutorial: Java Hibernate JPA Annotations Tutorial for Beginners. package net.codejava;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
public class HibernateUtil {
public static SessionFactory getSessionFactory() {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure() // configures settings from hibernate.cfg.xml
.build();
SessionFactory factory = new MetadataSources(registry)
.buildMetadata().buildSessionFactory();
return factory;
}
}This utility class simply returns a SessionFactory which is then used to perform CRUD operations. It is useful when using Hibernate in a standalone, simple Java application. <?xml version="1.0" encoding="UTF-8"?>
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/testdb</property>
<property name="connection.username">root</property>
<property name="connection.password">password</property>
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<mapping class="net.codejava.Product" />
</session-factory>
</hibernate-configuration>In this Hibernate configuration file, I use the property hibernate.hbm2ddl.auto=create-drop so Hibernate will create the database table at runtime, and drop it when finished. So you just need to create the database testdb in MySQL server. package net.codejava;
import java.util.List;
import org.hibernate.*;
import org.hibernate.query.*;
import org.junit.jupiter.api.*;
public class HibernateUtilTest {
private static SessionFactory sessionFactory;
private Session session;
@BeforeAll
public static void setup() {
sessionFactory = HibernateUtil.getSessionFactory();
System.out.println("SessionFactory created");
}
@AfterAll
public static void tearDown() {
if (sessionFactory != null) sessionFactory.close();
System.out.println("SessionFactory destroyed");
}
@Test
public void testCreate() {
}
@Test
public void testUpdate() {
}
@Test
public void testGet() {
}
@Test
public void testList() {
}
@Test
public void testDelete() {
}
@BeforeEach
public void openSession() {
session = sessionFactory.openSession();
System.out.println("Session created");
}
@AfterEach
public void closeSession() {
if (session != null) session.close();
System.out.println("Session closed\n");
}
}As you can see, I use lifecycle methods in JUnit to initialize SessionFactory before all test methods, initialize Session before each test method, and close them accordingly. I think this example explains the use of JUnit’s lifecycle methods perfectly.Update the test method that tests persisting a product as follows:@Test public void testCreate() {
System.out.println("Running testCreate...");
session.beginTransaction();
Product product = new Product("iPhone 10", 699);
Integer id = (Integer) session.save(product);
session.getTransaction().commit();
Assertions.assertTrue(id > 0);
}Write code for the testUpdate() method:@Test public void testUpdate() {
System.out.println("Running testUpdate...");
Integer id = 1;
Product product = new Product(id, "iPhone 11", 999);
session.beginTransaction();
session.update(product);
session.getTransaction().commit();
Product updatedProduct = session.find(Product.class, id);
assertEquals("iPhone 11", updatedProduct.getName());
}For testing retrieval operations, we test get a specific product and get all products. Update the testGet() method with below code:@Test
public void testGet() {
System.out.println("Running testGet...");
Integer id = 1;
Product product = session.find(Product.class, id);
assertEquals("iPhone 10", product.getName());
}Code for the testList() method:@Test
public void testList() {
System.out.println("Running testList...");
Query<Product> query = session.createQuery("from Product", Product.class);
List<Product> resultList = query.getResultList();
Assertions.assertFalse(resultList.isEmpty());
}And the last test method is for testing delete operation:@Test
public void testDelete() {
System.out.println("Running testDelete...");
Integer id = 1;
Product product = session.find(Product.class, id);
session.beginTransaction();
session.delete(product);
session.getTransaction().commit();
Product deletedProduct = session.find(Product.class, id);
Assertions.assertNull(deletedProduct);
}You can run each test individually. Note that run the testCreate() method first to create the table and first row. Then set hibernate.hbm2ddl.auto=none to keep the data for subsequent tests. You can execute all test methods by using test method order, as described in this guide.For visual actions, I recommend you to watch the following video:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.