如何使用SpringBootTest的依赖注入

时间:2017-11-30 20:16:54

标签: java unit-testing spring-boot dependency-injection

我有一个使用SpringBoot进行依赖注入的应用程序,应用程序工作正常,但测试失败,因为@Autowired字段在测试期间没有被注入。

@SpringBootApplication
public class ProcessorInterface {
    protected final static Logger logger = Logger.getLogger( ProcessorInterface.class );

    public static void main(String[] args) {
        try {
            SpringApplication.run(ProcessorInterfaceRunner.class, args);
        } catch (Exception ex) {
            logger.error("Error running  ProcessorInterface", ex);
        }
    }
}


@Component
@Configuration
@ComponentScan
public class ProcessorInterfaceRunner implements CommandLineRunner {
    protected final static Logger logger = Logger.getLogger( ProcessorInterface.class );

    @Autowired
    private RequestService requestService = null;
    @Autowired
    private ValidatorService validatorService = null;

    @Override
    public void run(String... args) throws Exception {

        ESPOutTransaction outTransaction = null;
        outTransaction = new ESPOutTransaction();
        // initialize outTransaction fields
        ...
        // done initializing outTransaction fields

        if (validatorService.isValid(outTransaction)) {
            System.out.println(requestService.getRequest(outTransaction));
        } else {
            System.out.println("Bad Data");
        }
    }
}


@Service
public class ESPRequestService implements RequestService<ESPOutTransaction> {

    @Autowired
    ValidatorService validatorService = null;

    @Override
    public String getRequest(ESPOutTransaction outTransaction) throws IllegalArgumentException {
        if (!validatorService.isValid(outTransaction)) {
            throw new IllegalArgumentException("Invalid parameters in transaction object. " + outTransaction.toString());
        }

        StringBuffer buff = new StringBuffer("create request XML");
        buff.append("more XML");
        return buff.toString();
    }
}


@Service
public class ESPValidatorService implements ValidatorService {
    private static org.apache.log4j.Logger logger = Logger.getLogger(ESPValidatorService.class);

    // declare some constants for rules
    private static final int MAX_LENGTH_XYZ = 3;

    @Override
    public boolean isValid(OutTransaction outTransaction) {
        ESPOutTransaction espOutTransaction = (ESPOutTransaction)outTransaction;
        boolean isValid = true;

        if (espOutTransaction == null) {
            logger.warn("espOutTransaction is NULL");
            isValid = false;
        } else {
            // XYZ is required
            if (espOutTransaction.getXYZ() == null) {
                logger.warn("XYZis NULL\r\n" + espOutTransaction.toString());
                isValid = false;
            }
            // XYZ max length = MAX_LENGTH_XYZ
            if (espOutTransaction.getXYZ() != null && espOutTransaction.getPubCode().trim().length() > MAX_LENGTH_XYZ) {
                logger.warn("XYZis too long (max length " + MAX_LENGTH_XYZ + ")\r\n" + espOutTransaction.toString());
                isValid = false;
            }
        }
        return isValid;
    }
}

当我运行应用程序时,这些都可以正常工作并获得良好的输出。当我尝试测试时,它失败了,因为它无法找到ESPValidatorService注入ESPRequestService

@RunWith(Suite.class)
@SuiteClasses({ ESPOutTransactionValidatorTest.class, ESPRequestTest.class })
public class AllTests {}


@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ESPRequestService.class})
public class ESPRequestTest {

    @Test
    public void testGetRequest() {
        ESPRequestService requestService = new ESPRequestService();

        String XYZ = "XYZ";

        ESPOutTransaction outTransaction = null;
        outTransaction = new ESPOutTransaction();
        outTransaction.setXYZ(XYZ);

        String strRequest = "some expected request XML";
        String request = requestService.getRequest(outTransaction);
        assertEquals(request, strRequest);
    }
}


@RunWith(SpringRunner.class)
@SpringBootTest(classes = ESPValidatorService.class)
public class ESPOutTransactionValidatorTest {

    @Test
    public void testIsValid() {
        ESPValidatorService validatorService = new ESPValidatorService();

        ESPOutTransaction outTransaction = null;
        // test request = null
        assertFalse(validatorService.isValid(outTransaction));

        String XYZ = "XYZ";

        outTransaction = new ESPOutTransaction();
        outTransaction.setXYZ(XYZ);

        // test all good
        assertTrue(validatorService.isValid(outTransaction));

        // test XYZ
        outTransaction.setXYZ(null);
        assertFalse(validatorService.isValid(outTransaction));
        outTransaction.setXYZ("ABCD"); // too long
        assertFalse(validatorService.isValid(outTransaction));
        outTransaction.setXYZ(XYZ);
    }
}

如何让单元测试自动接线?

1 个答案:

答案 0 :(得分:2)

我看到两个问题:

1)您不依赖于Spring bean,而是使用new运算符创建实例。

而不是写作:

ESPRequestService requestService = new ESPRequestService();

你应该让Spring注入实例:

@Bean
ESPRequestService requestService;

2)@SpringBootTest配置不正确。

在每个测试中,您在classes的{​​{1}}属性中指定了一个非常具体的bean类:

@SpringBootTest

@SpringBootTest(classes = ESPValidatorService.class)
public class ESPOutTransactionValidatorTest {

@SpringBootTest(classes = {ESPRequestService.class}) public class ESPRequestTest { 的{​​{1}}属性用于指定用于加载ApplicationContext的带注释的类。

  

用于加载ApplicationContext的带注释的类。能够   也可以使用classes指定。如果不   定义了显式类,测试将查找嵌套   @SpringBootTest课程,然后再回到   @ContextConfiguration(classes=...)搜索。

因此,可能无法在Spring容器中发现和加载应用程序的所有配置类和bean。

为了能够在测试期间加载所有应用程序bean,最简单的方法是不在@Configuration注释中指定SpringBootConfiguration属性:

classes

它将查找包含@SpringBootTest的Spring bean 理想情况下,它会找到您应用程序的@SpringBootTest public class ESPRequestTest { ...} bean 如果测试类的包位于@SpringBootConfiguration类的包(或更低级别)内,则应自动发现它。

否则另一种方法是指定一个允许加载所有必需bean的配置:

@SpringBootApplication