Recently, I started learning unit testing due to project requirements. However, it is stuck where the test framework is integrated with Spring and cannot start the Spring container, causing the beans used in the test class to not be injected automatically. I did a lot of research, and finally solved both JUnit4 and TestNG’s integration problems with Spring.

Lead to

The introduction of the jar package

We need to scan the class, we need the Spring-context.

Spring needs to be integrated with a testing framework, so spring-test is required.

When using junit 4 tests, you need to introduce junit.

If TestNG is used, you need to import TestNG.

The complete POM.xml file reads as follows:

<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zcl</groupId>
  <artifactId>test</artifactId>
  <version>1.0 the SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.6. RELEASE</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.6. RELEASE</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>6.14.3</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

</project>
Copy the code

Create the method to be tested

Create a new class Greeting

package com.zcl;

import org.springframework.stereotype.Component;

/ * * *@author: changle
 * @time: the 2019-06-18 05:16 * /
@Component
public class Greeting {

    public void sayHello(a) {
        System.out.println("Hello?"); }}Copy the code

The class contains only one simple method that we use to test.

Create the Spring configuration file

Create the applicationContext.xml file in the Resources folder

<?xml version="1.0" encoding="UTF-8"? >
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <context:component-scan base-package="com.zcl"/>

</beans>
Copy the code

Just add the packet scan.

JUnit4

In IDEA, we can quickly create a test class with the same package name in the test folder by pressing Command + Shift + t on the class name.

Testing library

We write a simple test method based on the generated class and add some configuration that integrates Spring.

package com.zcl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/ * * *@author: changle
 * @time: the 2019-06-18 05:19 * /
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class GreetingTest extends AbstractJUnit4SpringContextTests {

    @Autowired
    private Greeting greeting;

    @Test
    public void testSayHello(a) {
        System.out.println("JUnit4 tests begin");
        greeting.sayHello();
        System.out.println("JUnit4 test completed"); }}Copy the code

First, with the @runwith annotation, JUnit use cases are executed in Runner. With this annotation, we can specify the Runner we want for our test class, and since we are integrating with Spring, we choose SpringJUnit4ClassRunner.

And then @contextConfiguration. This annotation loads the file we filled in to inject the beans we need to use.

Our class inherits the Spring provides AbstractJUnit4SpringContextTests this interface, used to get the Application Context.

Run the test case and get something like this:

TestNG

You still create test cases, the only difference from JUnit is the way you get the Application Context.

package com.zcl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

/ * * *@author: changle
 * @time: the 2019-06-18 05:45 * /
@ContextConfiguration("classpath:applicationContext.xml")
public class GreetingTest extends AbstractTestNGSpringContextTests {

    @Autowired
    private Greeting greeting;

    @Test
    public void testSayHello(a) {
        System.out.println("TestNG test start");
        greeting.sayHello();
        System.out.println("TestNG test completed"); }}Copy the code

There is also @ContextConfiguration to introduce the Spring configuration file.

TestNG no longer needs to join Runner.

Test class inheritance is AbstractTestNGSpringContextTests, such ability can access to the Application Context.

Run the test case and the result is shown below

conclusion

Both frameworks are similar in configuration to Spring integration, and once you’ve learned how to integrate a test framework with Spring, you can easily write unit tests. Both testing frameworks also support many kinds of tests and will continue to share use cases for their other features.