发表于: 2020-10-10 23:07:17
1 1395
今天完成的事情:
遇到的问题:
Spring整合JUnit(参考网址:https://zhuanlan.zhihu.com/p/41664893)
一、JUnit 常用注解的简单使用
1、常用注解
- @Test::测试方法
- @Ignore:被忽略的测试方法:加上之后,暂时不运行此段代码
- @Before:每一个测试方法之前运行
- @After:每一个测试方法之后运行
- @BeforeClass:方法必须必须要是静态方法(static 声明),所有测试开始之前运行,注意区分 @Before
- @AfterClass:方法必须要是静态方法(static 声明),所有测试结束之后运行,注意区分 @After
2、JUnit 的简答使用
(1)添加 JUint 依赖
<!-- 单元测试Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
(2)测试代码
public class JunitTest1 {
private UserService userService;
@Before
public void init() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
userService = (UserService) context.getBean("userService");
}
@Test
public void test() {
userService.saveUser();
}
}
这里我们使用了 @Before 注解来获取 Spring 容器,并获取到需要使用的 bean 实例。这样就可以做到把业务代码和获取 Spring 容器的代码分离开来,无论有多少个业务方法需要测试,都只需要添加一个 @Test 标注的方法就可,无需重复获取 Spring 容器。但是这种只是简单的使用了 JUnit,而没有与 Spring 进行整合,如果我们想要做到不写 Spring 容器初始化的代码,只用 JUnit 是做不到的,下面我们来看看如何解决这个问题。
这里不知道bean是什么?去查了一下
spring bean是什么?(参考网址:https://www.awaimai.com/2596.html#comments)
Spring有跟多概念,其中最基本的一个就是bean,那到底spring bean是什么?
Bean是Spring框架中最核心的两个概念之一(另一个是面向切面编程AOP)。
是否正确理解 Bean 对于掌握和高效使用 Spring 框架至关重要。
遗憾的是,网上不计其数的文章,却没有简单而清晰的解释。
那么,Spring bean 到底是什么?
接下来我们用图文方式来解析这一个概念。
1 定义
Spring 官方文档对 bean 的解释是:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.
翻译过来就是:
在 Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。
概念简单明了,我们提取处关键的信息:
1.构成程序的主干
2.由Spring IoC容器实例化、组装和管理的对象。
作者提取的
- 1.bean是对象,一个或者多个不限定
- 2.bean由Spring中一个叫IoC的东西管理
- 3.我们的应用程序由一个个bean构成
第1和3好理解,那么IoC又是什么东西?
昨天了解了一下IoC,所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
举个例子,比如你中午不想动想点外卖,这时候没有美团你会怎么做呢?你还得自己出去,找一家店,吃完要到名片,下次就可以通过打电话下单了,但是你还想吃其他的,但并不知道那家好吃,总要吃过才知道。。。这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。
这时候出现了外卖软件,所有商家会在上面登记注册,无论你吃中餐还是西餐都可以在上面找到。你想好要求,然后在上面下单,就会给你送过来。简单明了,如果商家选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有外卖平台这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
2 控制反转(IoC)
控制反转英文全称:Inversion of Control,简称就是IoC
。
控制反转通过依赖注入(DI)方式实现对象之间的松耦合关系。
程序运行时,依赖对象由【辅助程序】动态生成并注入到被依赖对象中,动态绑定两者的使用关系。
Spring IoC容器就是这样的辅助程序,它负责对象的生成和依赖的注入,让后在交由我们使用。
简而言之,就是:IoC就是一个对象定义其依赖关系而不创建它们的过程。
这里我们可以细分为两个点。
2.1 私有属性保存依赖
第1点:使用私有属性保存依赖对象,并且只能通过构造函数参数传入,
构造函数的参数可以是工厂方法、保存类对象的属性、或者是工厂方法返回值。
假设我们有一个Computer
类:
package top.alanshelby.ComputerTest;
public class Computer {
private String cpu; // CPU型号
private int ram; // RAM大小,单位GB
public Computer(String cpu, int ram) {
this.cpu = cpu;
this.ram = ram;
}
}
我们有另一个Person
类依赖于Computer
类,符合IoC的做法是这样:
package top.alanshelby.ComputerTest;
public class Person {
private Computer computer;
public Person(Computer computer) {
this.computer = computer;
}
}
不符合IoC的做法如下:
// 直接在Person里实例化Computer类
public class Person {
private Computer computer = new Computer("AMD", 3);
}
// 通过【非构造函数】传入依赖
public class Person {
private Computer computer;
public void init(Computer computer) {
this.computer = computer;
}
2.2 让Spring控制类构建过程
第2点:不用new
,让Spring控制new
过程。
在Spring中,我们基本不需要 new
一个类,这些都是让 Spring 去做的。
Spring 启动时会把所需的类实例化成对象,如果需要依赖,则先实例化依赖,然后实例化当前类。
因为依赖必须通过构建函数传入,所以实例化时,当前类就会接收并保存所有依赖的对象。
这一步也就是所谓的依赖注入。
2.3 这就是IoC
在 Spring 中,类的实例化、依赖的实例化、依赖的传入都交由 Spring Bean 容器控制,
而不是用new
方式实例化对象、通过非构造函数方法传入依赖等常规方式。
实质的控制权已经交由程序管理,而不是程序员管理,所以叫做控制反转。
3 Bean?
至于bean,则是几个概念。
- 概念1:Bean容器,或称spring ioc容器,主要用来管理对象和依赖,以及依赖的注入。
- 概念2:bean是一个Java对象,根据bean规范编写出来的类,并由bean容器生成的对象就是一个bean。
- 概念3:bean规范。
bean规范如下:
- 所有属性为private
- 提供默认构造方法
- 提供getter和setter
- 实现serializable接口
二.Spring 整合 Junit
1、解决思路
针对上述问题,我们需要的是程序能自动帮我们创建容器。一旦程序能自动为我们创建 Spring 容器,我们就无须手动创建了,问题也就解决了。
但紧接的问题就是 JUnit 它本身不认识 Spring,更无法帮助创建 Spring 容器了,不过好在JUnit 给我们暴露了一个注解(@RunWith),可以让我们替换掉它的运行器。
这时,我们需要依靠 Spring 框架,因为它提供了一个运行器,可以读取配置文件(或注解)来创建容器。我们只需要告诉它配置文件在哪就行了。
@RunWith
关于@RunWith注解,官方文档是这么描述的:
当使用@RunWith注释类或扩展使用@RunWith注释的类时,JUnit将调用其引用的类以在该类中运行测试,而不是JUnit内置的运行程序。
2、配置步骤
(1)添加 spring-test 依赖
<!-- 添加 spring-test 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
(2)通过 @RunWith 注解,指定 Spring 的运行器,这里 Spring的运行器是SpringJunit4ClassRunner
//通过 @RunWith 注解,指定 Spring 的运行器,这里 Spring的运行器是SpringJunit4ClassRunner
@RunWith(SpringJUnit4ClassRunner.class)
(3)通过 @ContextConfiguration 注解,指定 Spring 运行器需要的配置文件路径或者配置类,这里由于我们使用的全注解的方式,所以指定的是配置类。
@ContextConfiguration(classes = SpringConfiguration.class)
//@ContextConfiguration(locations = "classpath:applicationContext.xml")
@Resource
private UserService userService;
3、测试类代码
package test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import top.alanshelby.config.SpringConfiguration;
import top.alanshelby.service.UserService;
import javax.annotation.Resource;
//通过 @RunWith 注解,指定 Spring 的运行器,这里 Spring的运行器是SpringJunit4ClassRunner
@RunWith(SpringJUnit4ClassRunner.class)
//通过 @ContextConfiguration 注解,指定 Spring 运行器需要的配置文件路径或者配置类,这里由于我们使用的全注解的方式,所以指定的是配置类。
@ContextConfiguration(classes = SpringConfiguration.class)
//@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JunitTest2 {
@Resource
private UserService userService;
@Test
public void test() {
userService.saveUser();
}
}
明天计划的事情:
查看日志,并转成Debug模式,练习调试,学会查看单步执行时的变量值。
收获:对junit更了解了,对spring认识加深了
评论