吐了!一个关键字,纠错两小时,看了十几篇博客。。。。最后重新建测试类发现@test又有用,结果发现是因为默认的tests测试类没有public关键字!
这个破错改了两小时。。。
==后续来了:==
建项目的时候是默认的2.3.0,所以默认创建的类结构应该是2.3.0版本的。
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.3.0.relea</version> <relativepath/> <!-- lookup parent from repository --> </parent>
emmm。之前因为改成了2.1.7.relea,版本不同,项目的结构也不同。
现在用回2.3.0relea
是可以正常跑的。。。而且也没有了@runwith注解
近期,项目需要写单元测试。我着手的项目是用springboot写的。所以就简单的研究了一下如何使用。在使用中遇到不少问题,不得已换了一种方式写测试用例,写完之后总感觉不太爽。今天在spring官网上学一个新的用法,发现这种测试方法使用后没有问题。所以来写一点笔记。
springboot提供注解的方式编写单元测试,可以使用springboottest注解来标示测试类。
@runwith(springrunner.class)@springboottestpublic class springboottest{@testpublic void method(){}}
这样写只能解决没有一些配置文件的测试逻辑,比如没有数据库配置、数据库连接池配置等。如果有这些配置,你就需要这样写了。
@runwith(springrunner.class)@springboottest(class = app病假条怎么写lication.class)@testpublic void method(){}
这样就可以正常运行了。
测试controller类。使用了mock,网上大多流传的是下面这种方法,添加@webappconfiguration,使用mockmvc去进行单元测试,但是我的项目如下使用就出现了问题,执行的时候找不到controller类,网上百度了各种方法都不管用。都会报no bean of ‘controller’ type found错误。
@runwith(springrunner.class)@springboottest(class = application.class)@webappconfiguration public class controllertest { private mockmvc mockmvc; @autowired private webapplicationcontext wac; @before // 在测试开始前初始公路安全保护条例释义化工作 public void tup() { this.mockmvc = mockmvcbuilders.webappcontexttup(this.wac).build(); } @test public void getmessagetest() throws exception { mvcresult mvcresult = mockmvc.perform(mockmvcrequestbuilders.get("/test/getmessage")) .anddo(mockmvcresulthandlers.print()).andreturn(); int status = mvcresult.getrespon().getstatus(); string content = mvcresult.getrespon().getcontentasstring(); asrt.asrttrue("success", status == 200); asrt.asrtfal("failed", status != 200); system.out.println("content" + content); }
后来换了一种方式直接new个controller。测试运行后不报no bean of ‘controller’ type found错误了,但是在controller中使用的rvice报了空指针异常npe,传递性就很明显了,controller是new的一个对象,所以注解不起作用,rvice就为null。
最后通过使用@autoconfiguremockmvc+@mockbean的方式可以实现简单的单元测试,并且不会对武术数据产生影响,且不会对数据库产生影响。
@runwith(springrunner.class)@springboottest(class = application.class)@autoconfiguremockmvcpublic class imkfmessagereportcontrollertest { /** * 初始化mockmvc */ @autowired private mockmvc mvc; /** * 测试的controller */ @mockbean private urcontroller urcontroller; @test public void geturlisttest() throws exception { mvcresult mvcresult = mvc.perform(mockmvcrequestbuilders.get("/ur/geturlist")) .andexpect(mockmvcresultmatchers.status().isok()) .anddo(mockmvcresulthandlers.print()) .andreturn(); string content = mvcresult.getrespon().getcontentasstring(); system.out.println("content" + content); }
上面是使用mockmvc,虽然能够验证短链接甚至rvi角的平分线的定义ce代码逻辑的正确性,能够正常测试接口的问题。但是缺点也不少,比如,覆盖率并没有提升。mockito是一个非常好用的单元测试工具,它的实现原理是继承要mock的类,将所有的公有方法进行重写
@runwith(mockitojunitrunner.class)public class urrvicetest { @mock private urmapper urmapper; @injectmocks private urrvice urrvice; @test public void savetest() throws exception { ur ur = new ur(); ur.turname(long.valueof("springboot")); when(urmapper.inrt(ur)).thenreturn(ur); int num = urrvice.save(ur); asrt.asrtequals("success", 1, 1); } }
使用runwwith(mockitojunitrunner.class)(也可以使用springbootrunner.class)来进行mocktio测试,注解@mock标记一个类或者接口是需要被mock的,在mock的过程中就相当于@resource,但是注意一点是mock是继承or实现了mock的类,所以mock出来的方法,全是null或者返回值为null。@injectmocks将所有的mock对象都放入需要测试的类的对象中。在上面的savetest方法里面调用到urmapper.inrt(),那么需要对urmapper.inrt()进行打桩,设置预期返回值。
打桩的时候需要注意:传递的参数(如果有)必须为调用时的同一个对象或者相同值,如果传入的参数是一个对象,那么需要对这个对象进行打桩,再打桩这个方法。比如,when(urmapper.inrt(ur)).thenreturn(rur),插入一个ur对象,如果ur插入之前要进行校验或者其他操作,需要对这个对象进行打桩(当然pojp对象可以直接new)。
如果插入的对象非常复杂,用构造方法来构造一个空对象,或者构造方法所用的对象不能直接构造,但是没有public的方法来设置值,该如何解决这个问题?我们知道一个对象的类可能有get方法(不一定是get,但是只要我们想获取这个对象中的参数,那么就有public的方法获取),我们可以通过mock这个对象,在将要测试的方法体内,如果某行调用了这个对象的任意方法(tostring()、equals()、get()),我们都可以以相同的参数(如果遇到参数未知可以用any(),一般都能知道)进行打桩后设置返回值,这样就能通过参数校验等环节,执行后面的代码逻辑,同时能够提高覆盖率,伪代码如下。
@mock private ur ur; when(ur.get(eq("urname"))).thenreturn("testadmin"); when(ur.get(eq("q"))).thenreturn(4); when(ur.get(eq("password"))).thenreturn("123456"); when(ur.get(eq("u_id"))).thenreturn("654321");
mockito测试需要设置参数和预期返回值,在方法体中遇到的所有未知对象(除了方法体中new的对象不需要)都需要进行模拟,但是在springboot代码刚刚完成的初期时,跟想模拟真实场景下进行单元测试代码问题or配置问题,那么通过自动注入的方式引入对象是一种更好的选择。
providerrviceimpl.java -----服务类 import com.alibaba.dubbo.config.annotation.rvice;import com.example.demo.rvice.demorvice;@rvicepublic class providerrviceimpl implements demorvice { @override public string sayhello(string name) { return "hello " + name + " !"; }} demoapplicationtests.java -----测试类 @runwith(springrunner.class)@springboottestpublic class demoapplicationtests { @resource demorvice providerrvice; @test public void contextloads() { string result = providerrvice.sayhello("spring boot test"); system.out.println("result is "+result); asrt.asrtequals("success","hello spring boot test !" ,result); } }
这里需要注意的是demoapplicationtests 需要跟启《红色家书》选篇动类main在同一级目录下,如果跟mvc在同一层可以会出现部分bean扫描不到的情况。如目录层级很深或者程序启动比较慢的话,可以去掉springboottest(去掉后就不启动程序,只会运行该测试),运行一下,测试结果如下:
通过这种注解的方式,可以测试dubbo连接(refernce注解),可以测试controller层,redis数据,mysql数据,都会真实模拟,你只需要在注入你需要测试的类,在类的入口传入测试参数,在测试过程中,最好采用debug的方式,这样你可以看到每一步的数据,也便于定位程序的问题(当然也可以出现问题时使用debug)。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。
本文发布于:2023-04-04 15:47:05,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/41158265630e0f2a5b24a41263a65525.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:SpringBoot单元测试使用@Test没有run方法的解决方案.doc
本文 PDF 下载地址:SpringBoot单元测试使用@Test没有run方法的解决方案.pdf
留言与评论(共有 0 条评论) |