在开发过程中,有时候需要对正在开发的某些功能进行测试。我们可以使用很多种方式,这里概括介绍对比几种方式。
第一种就是在当前类中新建一个main方法,在main方面里面调用集成的功能,这种方式简单,但是局限性比较多,主要有以下缺点:
(1)当前类中只能有一个main方法,如果开发完某一功能再测试另外一个功能,每次都要修改main方法里面的内容,特别是不方便进行来回切换测试。
(2)main方法不能直接调用service层或者dao层的方法,虽然可以通过上下文的工具类来进行调用,无形之中需要额外编写很多代码,并且这种单元测试的方式与原本的业务实现方式已经有所偏离。失去了进行单元测试的意义。因为原有的功能就是直接调用service层或者dao层的方法,在main方法中进行单元测试却换了另外一种方式调用。
(3)main方法申明的方式是:public static void main,由此可以看出main方法是一个static静态方法,所以在main方法里面无法调用非静态方法,因为Java中的静态方法不能调用非静态方法。具体解释就是:静态方法是属于类的,即静态方法是随着类的加载而加载的,在加载类时,程序就会为静态方法分配内存,而非静态方法是属于对象的,对象是在类加载之后创建的,也就是说静态方法先于对象存在。当你创建一个对象时或者说对象初始化之后,程序才会为其在堆中分配内存,也就是说对于非静态方法,在对象创建的时候程序才会为其分配内存,然后通过类的对象去访问非静态方法。这也就解释了静态方法为什么不能调用非静态方法,因为对象未存在时非静态方法也不存在,静态方法自然不能调用一个不存在的方法,造成资源还没准备好就直接去调用的矛盾。
第二种方式,就是封装成接口,然后把项目运行起来,模拟调用一下接口。这种方式虽然实现起来比较简单,但操作起来比较繁琐,主要有以下原因:
(1)每次修改代码,为了测试都需要把项目运行起来,等待项目启动也是一个比较耗时的过程,有些项目有各种不同环境的配置,要使项目在本地能顺利运行,得保证有一套本地可以访问的配置。
(2)项目启动运行之后,接口一般都有拦截,可以登录成功之后再调用接口,也可以把当前的接口设置取消拦截,在ShiroFilterFactoryBean里面设置anon不需要认证。这两种方式都不太可取,第一种方式每次都需要登录之后才能模拟调用,第二种方式修改了底层代码,如果误提交上线,该接口就存在安全隐患,无任何拦截。
第三种方式,就是集成junit单元测试,小编比较推荐这种,当然这种方式也有利有弊,先说一下弊端:
(1)junit单元测试的方法只能申明为void,并且不能携带请求参数,这也意味着参数需要写到方法里面,或者提前申明参数,反复测试时可能就需要手动修改参数。
(2)如果你在业务代码中记录日志使用到了如logback技术,在junit单元测试方法里面不能直接使用,有方法可以实现但比较繁琐。
(3)junit单元测试方法里面无法调用非静态方法,只能调用静态方法。
虽然有这些缺陷,但他的优点更突出,主要就是:不需要修改原来任何的业务代码、不需要启动项目就可以直接运行测试方法,多个方法都可以单独测试、可以自由切换环境进行测试等。接下来就重点讲解一下junit单元测试。
1、集成maven依赖,在pom.xml中加入以下代码:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2、Springboot项目集成junit单元测试,新建test目录文件夹,与main目录同级,结构层次如下
3、编写测试代码,模板如下:
详细说明:
(1)junit单元测试类上要加一些注解,主要注解说明如下:
@RunWith就是一个运行器,@RunWith(SpringRunner.class)指让类运行在Spring的测试环境,以便测试开始时自动创建Spring应用上下文。
@SpringBootTest替代了spring-test中的@ContextConfiguration注解,目的是加载ApplicationContext,启动spring容器。
@ActiveProfiles指定配置环境,我设置了四种环境,开发【dev】、测试【test】、演示【uat】和生产【pro】。在@ActiveProfiles注解上指定对应的配置就会使用对应的配置参数来执行方法。
(2)日志记录,最开始已经说明了在junit单元测试方法里面不能直接使用logback,我改用通用类日志LoggerFactory,也可以实现控制台的日志打印。
(3)在junit单元测试方法上,需要添加注解@Test,他的作用就是该方法可以不用main方法调用就可以测试出运行结果,是一种测试方法。
(4)在junit测试方法里面可以直接调用service方法或者dao层方法,跟正常的控制类controller里面调用一样。
(5)junit测试方法里面只能调用静态方法。
(6)junit测试方法不能带参,无返回值。
注意事项:有些项目在启动时需要去加载一些配置文件,比如我在项目启动时需要加载支付宝的参数文件zfbinfo_dev.properties,加载完之后才能获取到参数。在junit单元测试类中就不需要再去重写这个方法,如果重写反而获取不到参数,返回是空。