Spring测试框架springContextTest

本文介绍了解决SpringJUnit4ClassRunner在不同JUnit版本下遇到的兼容性问题的过程。作者首先遇到了SpringJUnit4ClassRunner要求JUnit 4.9或更高版本的问题,通过升级JUnit版本解决了该问题。随后又出现了Hamcrest类找不到的错误,最终通过添加Hamcrest依赖成功运行了测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    ssh版本:spring4.2/struts2.3/hibernate4;除了一些必要的jar包外,使用spring自带的测试框架,还要额外导入spring-test-4.2.2.jar。

junit使用的是junit4.7,相关测试代码如下:

package TestContext;

import java.util.List;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import entity.User;
import service.UserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:beans.xml")
@Transactional
public class ListActionTest extends AbstractTransactionalJUnit4SpringContextTests{
	
	
	private UserService userService;
	

	public UserService getUserService() {
		return userService;
	}


	@Resource
	public void setUserService(UserService userService) {
		this.userService = userService;
	}


	//@Rollback(true)默认true 
	@Test
	public void test(){
		User user = userService.getUser(50);
		System.out.println(user.getUname());
		
		List<User> users = userService.getUsers();
		System.out.println(users.size());
	}
	
}

run as junit Test时报错:

java.lang.ExceptionInInitializerError
     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
     at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
     at java.lang.reflect.Constructor.newInstance(Unknown Source)
     at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
     at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
     at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
     at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
     at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
     at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84)
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70)
     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalStateException: Failed to find class [org.junit.runners.model.MultipleFailureException]: SpringJUnit4ClassRunner requires JUnit 4.9 or higher.
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<clinit>(SpringJUnit4ClassRunner.java:102)
     ... 17 more

报错信息里提到:

SpringJUnit4ClassRunner requires JUnit 4.9 or higher

后来换成junit-4.12.jar,运行报错:

java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing

原来 Since JUnit 4.11 the junit.jar itself has no Hamcrest classes,后来导入harmcrest-core-1.3.jar,继续运行,ok!

转载于:https://my.oschina.net/u/2430057/blog/541291

<think>我们正在讨论的是在JUnit5测试中如何读取properties文件的内容。虽然之前的问题涉及了@TestPropertySource,但用户现在明确询问的是读取文件内容的方法,而不是如何通过Spring的测试工具注入属性。根据引用,有几种读取properties文件的方法,我们可以结合JUnit5的测试环境来使用。在JUnit5测试中,我们可以使用以下方法读取properties文件:1.使用Java原生的ClassLoader.getResourceAsStream()方法2.使用Spring的PropertiesLoaderUtils(如果项目中有Spring框架)3.使用java.util.Properties的load()方法由于用户特别提到JUnit5,我们假设测试可能是普通的JUnit5测试(不涉及Spring)或者集成了Spring(使用SpringExtension)。下面分别说明。方法一:纯Java方式(不依赖Spring)步骤:a.将properties文件放在test/resources目录下(例如:config.properties)b.使用ClassLoader获取输入流c.使用Properties对象加载流示例代码:```javaimportorg.junit.jupiter.api.Test;importjava.io.IOException;importjava.io.InputStream;importjava.util.Properties;publicclassReadPropertiesTest{@TestvoidreadPropertiesWithClassLoader()throwsIOException{//注意:文件路径相对于classpath的根,如果放在test/resources的根下,直接写文件名//如果放在test/resources/config目录下,则写"config/config.properties"StringfileName="test.properties";InputStreaminputStream=getClass().getClassLoader().getResourceAsStream(fileName);if(inputStream==null){thrownewIllegalArgumentException("filenotfound:"+fileName);}Propertiesproperties=newProperties();properties.load(inputStream);System.out.println(properties.getProperty("key1"));inputStream.close();}}```方法二:使用Spring的PropertiesLoaderUtils(需要Spring-core依赖)步骤:a.同样将文件放在test/resources目录b.使用ClassPathResource和PropertiesLoaderUtils示例代码(在Spring环境下,但即使没有Spring测试上下文也可以使用,因为只是工具类):```javaimportorg.junit.jupiter.api.Test;importorg.springframework.core.io.ClassPathResource;importorg.springframework.core.io.support.PropertiesLoaderUtils;importjava.io.IOException;importjava.util.Properties;publicclassReadPropertiesTest{@TestvoidreadPropertiesWithSpringUtils()throwsIOException{//注意:ClassPathResource的路径是从classpath根开始的,所以如果文件在根下,前面加斜杠或不加都可以(不加斜杠也是相对根)//但是一般建议使用绝对路径(以斜杠开头)表示从根开始ClassPathResourceresource=newClassPathResource("/test.properties");Propertiesproperties=PropertiesLoaderUtils.loadProperties(resource);System.out.println(properties.getProperty("key1"));}}```注意:第二种方法需要项目已经引入了Spring-core,如果没有,则使用第一种纯Java方式。方法三:使用JUnit5的扩展(如果结合SpringBoot测试)如果是在SpringBoot测试中,我们可以使用@PropertySource或者@TestPropertySource,但这是将属性注入到Spring环境中的方式,并不是直接读取文件内容。不过,如果测试类使用了SpringExtension,那么我们可以通过Environment对象获取属性,或者通过@Value注入。但是用户的问题是“读取properties文件内容”,所以更倾向于直接读取文件,而不是通过Spring容器。因此,方法一和方法二更合适。总结:-如果不想引入Spring,使用纯Java方式(方法一)。-如果项目中已有Spring-core,可以使用Spring的工具类(方法二)。注意事项:-确保properties文件在构建时被复制到classpath中(在Maven/Gradle项目中,放在src/test/resources目录下的文件会自动复制到testclasspath)。-文件路径的写法:使用ClassLoader时,不要以斜杠开头(或者以斜杠开头也可以,因为ClassLoader.getResourceAsStream()会处理),但一般不以斜杠开头。而Spring的ClassPathResource以斜杠开头表示绝对路径(从classpath根开始),不加斜杠也是从根开始(相对路径相对于根)。所以为了避免混淆,建议使用绝对路径(即从classpath根开始,写完整路径)。示例:假设文件结构src/test/resources|--test.properties|--config|--app.properties读取test.properties:纯Java方式:fileName="test.properties"或"/test.properties"(注意:ClassLoader.getResourceAsStream()对于以斜杠开头的路径可能在某些环境下不工作,所以通常不加斜杠)使用Spring:newClassPathResource("test.properties")或newClassPathResource("/test.properties")读取app.properties:纯Java方式:"config/app.properties"使用Spring:newClassPathResource("config/app.properties")另外,在Spring工具中也可以使用相对路径,但通常我们使用绝对路径(相对于classpath根)。如果文件不存在,两种方式都会抛出异常(或者返回null),所以需要处理。相关问题:1.在JUnit5测试中如何动态加载不同环境的properties文件?2.如何使用JUnit5的扩展来在测试前加载properties并设置到测试上下文中?3.在SpringBoot测试中,如何区分测试属性和主应用程序属性?4.如何读取多个properties文件并合并?5.在JUnit5的参数化测试中如何使用properties文件提供参数?</think>### 在 JUnit 5 中读取 `.properties` 文件的三种方法 #### 方法 1:使用 Java 原生 API(无需 Spring) ```java import org.junit.jupiter.api.Test; import java.io.InputStream; import java.util.Properties; class PropertiesTest { @Test void readProperties() throws Exception { // 从 classpath 根目录加载文件 InputStream input = getClass().getClassLoader() .getResourceAsStream("test.properties"); Properties props = new Properties(); props.load(input); // 加载属性文件 System.out.println("DB_URL: " + props.getProperty("db.url")); System.out.println("TIMEOUT: " + props.getProperty("app.timeout", "5000")); // 带默认值 } } ``` **关键点**: 1. 文件位置:`src/test/resources/test.properties` 2. `getResourceAsStream()` 路径规则: - 根目录文件:`"filename.properties"` - 子目录文件:`"config/filename.properties"` 3. 默认值:`getProperty(key, defaultValue)` #### 方法 2:使用 Spring 工具类(需 Spring Core) ```java import org.junit.jupiter.api.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; import java.util.Properties; class SpringPropertiesTest { @Test void readProperties() throws Exception { // 加载 classpath 中的文件 ClassPathResource resource = new ClassPathResource("config/test.properties"); Properties props = PropertiesLoaderUtils.loadProperties(resource); System.out.println("API_KEY: " + props.getProperty("api.key")); } } ``` **优势**: - 自动处理文件编码 - 支持占位符解析 `${}` - 路径以 `/` 开头表示绝对路径[^3] #### 方法 3:在 Spring 测试环境中使用 `@TestPropertySource` ```java import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) // JUnit 5 集成 Spring @TestPropertySource(locations = "classpath:test.properties") class SpringContextTest { @Value("${app.env}") // 属性自动注入 private String environment; @Test void testPropertyInjection() { System.out.println("ENVIRONMENT: " + environment); // 输出 "test" } } ``` ### 最佳实践建议 1. **文件位置**: ```mermaid graph LR A[src/test/resources] --> B[根目录属性文件] A --> C[/config/ 子目录属性文件] ``` 2. **路径处理**: - 正确:`new ClassPathResource("config/app.properties")` - 错误:`new ClassPathResource("src/test/resources/config/app.properties")` 3. **异常处理**: ```java try { // 加载代码 } catch (IOException ex) { // 文件不存在时的处理 throw new IllegalStateException("属性文件加载失败", ex); } ``` 4. **多文件加载**: ```java // Spring 方式 ClassPathResource[] resources = { new ClassPathResource("db.properties"), new ClassPathResource("app.properties") }; Properties combined = new Properties(); for (ClassPathResource res : resources) { PropertiesLoaderUtils.fillProperties(combined, res); } ``` ### 常见问题解决 **问题:文件找不到** ✅ 检查文件是否在 `src/test/resources` 目录 ✅ 使用 Maven/Gradle 清理并重新构建项目 **问题:中文乱码** ✅ 明确指定 UTF-8 编码: ```java try (Reader reader = new InputStreamReader( getClass().getResourceAsStream("/i18n/messages_zh.properties"), StandardCharsets.UTF_8)) { properties.load(reader); } ``` **问题:路径特殊字符** ✅ 对空格和特殊字符使用 URL 编码: ```java // 包含空格的文件名 ClassPathResource resource = new ClassPathResource("my%20config.properties"); ``` --- ### 相关问题 1. 如何在 JUnit 5 参数化测试中使用 properties 文件提供测试数据? 2. Spring Boot 测试中 `@TestPropertySource` 与 `application-test.properties` 的优先级顺序是什么? 3. 如何在测试中动态修改 properties 文件的值? 4. 多模块项目中如何跨模块读取 properties 文件? 5. 测试环境与生产环境的 properties 文件如何隔离管理? [^1]: [^2]: [^3]:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值