Junit 单元测试、BeanUtils、Properties类

本文详细介绍了Java开发中的Junit单元测试框架,包括基本使用、Assert断言工具类以及用于环境准备和清理的方法。接着讲解了内省(Introspector)的概念,探讨了为何需要学习内省以及如何操作Java对象属性。最后,阐述了Properties类在处理配置文件中的应用,包括加载、保存和写入配置文件。
一、 Junit单元测试

1.1. Junit单元测试框架的基本使用

 

一、搭建环境:

导入junit.jar包(junit4

 

二、写测试类:

0,一般一个类对应一个测试类。

1,测试类与被测试类最好是放到同一个包中(可以是不同的源文件夹)

2,测试类的名字为被测试类的名字加Test后缀。

 

三:写测试方法:

0,一般一个方法对应一个单元测试方法。

1,测试方法的名字为test前缀加被测试方法的名字,如testAddPerson()

2,单元测试方法上面要加上@Test注解(org.junit.Test)!

3,单元测试方法不能有参数,也不能有返回值(返回void)!测试的方法不能是静态的方法。

 

四、测试方法的基本使用:

1,可以单独执行一个测试方法,也可以一次执行所有的、一个包的、一个类中所有的测试方法。

2,执行完后,显示绿色表示测试成功;显示红色表示测试失败(抛异常后会测试失败)。

 

1.2. Assert断言工具类

 

其中有一些静态的工具方法(不符合期望就抛异常):

 

assertTrue(...) 参数的值应是true

assertFalse(...) 参数的值应是false  

 

assertNull(...) 应是null

assertNotNull(...) 应是非null的值

 

assertSame(...) 使用==比较的结果为true(表示同一个对象)

AssertNotSame(...) 使用==比较的结果为false

 

assertEquals(...) 两个对象equals()方法比较结果为true

 

1.3. 用于准备环境、清理环境的方法

@Test

表示单元测试方法。

 

@Before

所修饰的方法应是非static的(且没有参数,返回值为void)。

表示这个方法会在本类中的每个单元测试方法之前都执行一次。

 

@After

所修饰的方法应是非static的(且没有参数,返回值为void)。

表示这个方法会在本类中的每个单元测试方法之后都执行一次。

 

 

@BeforeClass

所修饰的方法应是static的(且没有参数,返回值为void)。

表示这个方法会在本类中的所有单元测试方法之前执行,只执行一次。

 

@AfterClass

所修饰的方法应是static的(且没有参数,返回值为void)。

表示这个方法会在本类中的所有单元测试方法之后执行,只执行一次。

 

 

二、 内省(Introspector)

为什么要学内省?

开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

 

内省是用于操作java对象的属性的,那么以下问题我们必须要清楚。

 

问题一: 什么是Java对象的属性和属性的读写方法?

 

问题二: 如何通过内省访问到javaBean的属性 ?

 

1. 通过PropertyDescriptor类操作Bean的属性.

 

public static void testPropertyDescriptor() throws Exception{

Person p = new Person();

PropertyDescriptor propertyDescriptor =  new PropertyDescriptor("id",Person.class);

//获取属性的写的方法。

Method writeMethod = propertyDescriptor.getWriteMethod();

Method readMethod = propertyDescriptor.getReadMethod();

propertyDescriptor.getReadMethod();

writeMethod.invoke(p, 12);

System.out.println(readMethod.invoke(p, null));

}

 

 

2. 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。

 

public static void testIntrospector() throws Exception{

BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);

PropertyDescriptor[]  descriptor = beanInfo.getPropertyDescriptors();

for(PropertyDescriptor itemProperty : descriptor){

System.out.println(itemProperty.getReadMethod().getName());

}

}

 

存在的问题: sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils

 

public static void main(String[] args) throws Exception {

Person p = new Person();

ConvertUtils.register(new Converter() {

 

@Override

public Object convert(Class type, Object value) {

 try {

if(value!=null){

 

 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");

 Date d = dateFormat.parse((String) value);

 return d;

 }

} catch (ParseException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

return null;

}

}, Date.class);

 

BeanUtils.setProperty(p,"id","110");

BeanUtils.setProperty(p,"name","狗娃");

BeanUtils.setProperty(p, "birthDay","1992 12 12");

System.out.println(p.getId() +"=="+ p.getName()+"======"+p.getBirthDay());

}

 

三、 Properties类与配置文件

1.1 Properties配置文件说明

Properties类对应.properties文件。文件内容是键值对,键值对之间使用"="或空格隔开。开头是"#"的表示注释

 

Properties类在加载.properties文件时使用的iso8859-1的编码。所以这个文件中的中文要特殊处理:如果这个配置文件中有中文就必须要进行转义,使用native2ascii.exe命令操作:

native2ascii d:/my.properties d:/my2.properties

 

使用Properties类中的load(InputStream) 方法可以加载配置文件,使用其中的store(OutputStream) 方法可以保存配置到指定文件。

 

更多的信息可以看Properties类的API文档。

 

1.2 加载配置文件

一、 Junit单元测试

1.1. Junit单元测试框架的基本使用

 

一、搭建环境:

导入junit.jar包(junit4

 

二、写测试类:

0,一般一个类对应一个测试类。

1,测试类与被测试类最好是放到同一个包中(可以是不同的源文件夹)

2,测试类的名字为被测试类的名字加Test后缀。

 

三:写测试方法:

0,一般一个方法对应一个单元测试方法。

1,测试方法的名字为test前缀加被测试方法的名字,如testAddPerson()

2,单元测试方法上面要加上@Test注解(org.junit.Test)!

3,单元测试方法不能有参数,也不能有返回值(返回void)!测试的方法不能是静态的方法。

 

四、测试方法的基本使用:

1,可以单独执行一个测试方法,也可以一次执行所有的、一个包的、一个类中所有的测试方法。

2,执行完后,显示绿色表示测试成功;显示红色表示测试失败(抛异常后会测试失败)。

 

1.2. Assert断言工具类

 

其中有一些静态的工具方法(不符合期望就抛异常):

 

assertTrue(...) 参数的值应是true

assertFalse(...) 参数的值应是false  

 

assertNull(...) 应是null

assertNotNull(...) 应是非null的值

 

assertSame(...) 使用==比较的结果为true(表示同一个对象)

AssertNotSame(...) 使用==比较的结果为false

 

assertEquals(...) 两个对象equals()方法比较结果为true

 

1.3. 用于准备环境、清理环境的方法

@Test

表示单元测试方法。

 

@Before

所修饰的方法应是非static的(且没有参数,返回值为void)。

表示这个方法会在本类中的每个单元测试方法之前都执行一次。

 

@After

所修饰的方法应是非static的(且没有参数,返回值为void)。

表示这个方法会在本类中的每个单元测试方法之后都执行一次。

 

 

@BeforeClass

所修饰的方法应是static的(且没有参数,返回值为void)。

表示这个方法会在本类中的所有单元测试方法之前执行,只执行一次。

 

@AfterClass

所修饰的方法应是static的(且没有参数,返回值为void)。

表示这个方法会在本类中的所有单元测试方法之后执行,只执行一次。

 

 

二、 内省(Introspector)

为什么要学内省?

开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

 

内省是用于操作java对象的属性的,那么以下问题我们必须要清楚。

 

问题一: 什么是Java对象的属性和属性的读写方法?

 

问题二: 如何通过内省访问到javaBean的属性 ?

 

1. 通过PropertyDescriptor类操作Bean的属性.

 

public static void testPropertyDescriptor() throws Exception{

Person p = new Person();

PropertyDescriptor propertyDescriptor =  new PropertyDescriptor("id",Person.class);

//获取属性的写的方法。

Method writeMethod = propertyDescriptor.getWriteMethod();

Method readMethod = propertyDescriptor.getReadMethod();

propertyDescriptor.getReadMethod();

writeMethod.invoke(p, 12);

System.out.println(readMethod.invoke(p, null));

}

 

 

2. 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。

 

public static void testIntrospector() throws Exception{

BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);

PropertyDescriptor[]  descriptor = beanInfo.getPropertyDescriptors();

for(PropertyDescriptor itemProperty : descriptor){

System.out.println(itemProperty.getReadMethod().getName());

}

}

 

存在的问题: sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils

 

public static void main(String[] args) throws Exception {

Person p = new Person();

ConvertUtils.register(new Converter() {

 

@Override

public Object convert(Class type, Object value) {

 try {

if(value!=null){

 

 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");

 Date d = dateFormat.parse((String) value);

 return d;

 }

} catch (ParseException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

return null;

}

}, Date.class);

 

BeanUtils.setProperty(p,"id","110");

BeanUtils.setProperty(p,"name","狗娃");

BeanUtils.setProperty(p, "birthDay","1992 12 12");

System.out.println(p.getId() +"=="+ p.getName()+"======"+p.getBirthDay());

}

 

三、 Properties类与配置文件

1.1 Properties配置文件说明

Properties类对应.properties文件。文件内容是键值对,键值对之间使用"="或空格隔开。开头是"#"的表示注释

 

Properties类在加载.properties文件时使用的iso8859-1的编码。所以这个文件中的中文要特殊处理:如果这个配置文件中有中文就必须要进行转义,使用native2ascii.exe命令操作:

native2ascii d:/my.properties d:/my2.properties

 

使用Properties类中的load(InputStream) 方法可以加载配置文件,使用其中的store(OutputStream) 方法可以保存配置到指定文件。

 

更多的信息可以看Properties类的API文档。

 

1.2 加载配置文件

 

1.3 写配置文件

1.4 使用Properties

public class DBUtil {

 

static Properties properties = new Properties();

 

static{

try {

Class clazz = DBUtil.class;

InputStreamReader fileReader =

new InputStreamReader(clazz.getResourceAsStream("/db.properties"));

properties.load(fileReader);

} catch (IOException e) {

e.printStackTrace();

}

}

public static String getUserName(){

String userName =properties.getProperty("userName");

return userName;

}

 

public static String getPassword(){

return properties.getProperty("password");

}

public static void main(String[] args) {

System.out.println("用户名:"+ getUserName());

System.out.println("密码: "+  getPassword());

}

}

<think>好的,我现在需要帮助用户解决在Spring Boot测试中Mapper和Service注入为null的问题。用户之前已经询问过非Controller层的Mapper注入问题,现在具体到测试中的情况,并且引用了几个相关的例子和解决方案。我需要结合之前的回答和用户提供的引用内容,给出具体的解决方案。 首先,用户提到的测试使用了@SpringBootTest,但注入的bookMapper仍然为null。这可能是因为测试没有正确配置或者依赖项缺失。根据之前的回答,常见的解决方案包括确保组件被Spring管理、使用ApplicationContextAware获取Bean、检查Mapper扫描配置等。现在需要将这些方法应用到测试中。 接下来,用户提供的引用中,引用1是一个测试的例子,但可能缺少正确的配置。引用2展示了在Controller中使用单例模式时可能遇到的问题,这可能涉及到Bean的作用域。引用3是一个工具BeanUtils,用于手动获取Bean,这在测试中可能有用。引用4提到了单元测试中Service为null的问题,可能与测试环境的配置有关。 我需要考虑测试中常见的导致注入失败的原因,比如缺少@RunWith或@ExtendWith注解,导致测试没有被Spring上下文管理。另外,检查@SpringBootTest是否正确配置了启动,确保组件扫描和配置被加载。同时,可能需要检查测试依赖是否正确,比如是否包含了Spring Boot Test Starter。 另外,用户之前的问题中提到了使用ApplicationContextAware来获取Bean,这在测试中可能同样适用,但更常见的做法是通过测试支持注解来注入依赖。如果自动注入失败,可以尝试手动从应用上下文中获取Bean。 还需要考虑测试的包结构是否与主应用程序的包结构一致,如果不在同一包下,可能需要显式指定@ComponentScan或者@SpringBootTest的classes属性来加载配置。 此外,用户可能在测试中使用了错误的注解,比如JUnit4和JUnit5的混合使用,导致上下文未正确初始化。需要确保使用正确的测试注解,如JUnit5的@ExtendWith(SpringExtension.class)或者直接使用@SpringBootTest,后者已经包含必要的扩展。 最后,可能涉及到事务管理,测试默认会回滚事务,但这通常不会导致注入失败,而是数据访问的问题。不过用户的问题是关于注入为null,所以可能不相关,但需要确认。 综合以上思考,解决方案应包括:检查测试的注解是否正确,确保测试位于正确的包路径,使用@Autowired或手动获取Bean,检查依赖配置,以及可能的静态方法处理。</think>#### Spring Boot测试依赖注入失败解决方案 在测试中出现`Mapper`/`Service`注入为null,本质是测试环境未正确初始化Spring容器。以下是针对性的解决方案: --- ### 一、基础配置验证 1. **必须的测试注解** ```java @SpringBootTest // 加载完整应用上下文 @ExtendWith(SpringExtension.class) // JUnit5必须 public class BookMapperTestCase { @Autowired private BookMapper bookMapper; } ``` - 缺少`@ExtendWith`会导致上下文未初始化[^1] - 使用JUnit4时需替换为`@RunWith(SpringRunner.class)` 2. **包路径验证** - 测试必须与主启动同包或在其子包下 - 跨包测试需显式指定: ```java @SpringBootTest(classes = Application.class) // 指定主启动 ``` --- ### 二、特定场景解决方案 #### 场景1:常规Service/Mapper注入失败 ```java @SpringBootTest public class MyServiceTest { @Autowired private UserService userService; // 注入为null // 解决方案:添加构造器注入 @Autowired public MyServiceTest(UserService userService) { this.userService = userService; } } ``` *关键点:优先使用构造器注入可提前暴露配置错误* #### 场景2:静态工具中的注入 参考引用[3]的`BeanUtils`方案: ```java @SpringBootTest public class StaticUtilsTest { @Test void testStaticAccess() { UserMapper mapper = BeanUtils.getBean(UserMapper.class); Assertions.assertNotNull(mapper.selectById(1)); } } ``` --- ### 三、高级排查步骤 1. **检查测试依赖** ```xml <!-- pom.xml必须包含 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> ``` 2. **查看启动日志** - 关注是否有`NoSuchBeanDefinitionException` - 检查是否漏加`@MapperScan`导致Mapper未注册[^3] 3. **事务回滚验证** ```java @SpringBootTest @Transactional // 默认自动回滚 public class TransactionTest { @Test @Rollback(false) // 关闭回滚 void testWithRealCommit() { // 测试数据库操作 } } ``` --- ### 四、测试配置最佳实践 ```java @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.NONE, // 非web环境 properties = "spring.main.lazy-initialization=true" // 按需加载Bean ) @ActiveProfiles("test") // 指定测试profile @AutoConfigureMockMvc // 需要web环境时添加 public class OptimizedTest { @MockBean // 模拟外部依赖 private ThirdPartyService thirdPartyService; } ``` --- ### 五、常见错误对照表 | 现象 | 解决方案 | |------|----------| | `NoSuchBeanDefinitionException` | 检查`@Component`/`@Service`注解 | | `BeanCreationException` | 验证依赖的Bean是否可用 | | `NullPointerException` | 确认测试方法不是static型 | | 部分Bean为null | 检查`@SpringBootTest`的classes参数 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值