Spring boot的基础总结(七)-------Mock和restassured的合体

一.序
最近在搞Spring boot的接口测试的问题,为了保证代码的质量和功能实现,想想好像只有Junit可以帮我搞一搞。但是很多问题接踵而至。

我的服务和其它服务有关联(有点像微服务),那在脱离了其它服务依赖的时候,我该如何进行测试?

那么神奇的我找了很多资料,总算总结了以下两个可执行的东西。
(一)Mock可以对数据进行打桩,模拟对象返回
(二)restassured可以简化 HTTP Builder 顶层 ,验证REST服务
本身rest-assured是没办法进行数据打桩的,所以要搭配Mock在一起。
而Mock本身也是不跟rest-assured有什么关联。但是!!!rest-assured将MockMVC集合在一起了,所以两个的配合得到了一定保证。

二.Mock
mock就是创建一个类的虚假的对象,在测试环境中,用来替换掉真实的对象
可以解决以下两个问题:

1.验证这个对象的某些方法的调用情况,调用了多少次,参数是什么等等
2.指定这个对象的某些方法的行为,返回特定的值,或者是执行特定的动作

而Mock,我们经常使用的就是Mockito里面的东西。
在Springboot中,我们增加依赖

      <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>

创建TestControl,并构造hello方法

public class TestController {
  @RequestMapping("/hello")
    @ResponseBody
    public String hello() {
        return "user";
    }
}

在JunitTest类中引入静态资源

import static org.mockito.Mockito.*;
import static org.junit.Assert.*;

然后我们来使用mockito进行测试。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TestControllerTest {
   @MockBean
    TestController testController;
	   @Test
    void hello() throws RetException {
        //.当调用control中的he方法,则返回我们指定的值。。
        Mockito.when(testController.he()).thenReturn("ReTurnValue");
		//执行后,可以发现,本身返回"user"的方法,现在返回"ReTurnValue"
        System.out.println(testController.he());
        }
}

这里只介绍最简单的用法,总结一个Mockito就是模仿你本身的对象,并且返回你自己“设定”的返回值。可以看到,Mockito的职能并不包含去测试Controller层
更多的mockito使用方法
不过为了更好理解下面的合体,这里还要在多介绍一些注解。
可以看到Mock对象是加了@MockBean注解的。
这里可以看大佬写的

@McokBean:是将模拟对象添加到Spring应用程序上下文中,这个模拟会替换上下文里面任何相同类型 Control层里面有Service.此时,模拟Service.
@Mock:Mock声明的对象,对函数的调用均执行mock(即虚假函数),不执行真正部分。
@Spy:声明的对象,对函数的调用均执行真正部分。保留真实对象,除非你设定了确定的返回,否则按照真实的走。
@InjectMock:InjectMock声明的对象,创建该类的实例,并将使用@Mock注解创建的模拟注入该实例(不懂的看到后面合体就知道了)
可以说其余用@Mock注解创建的mock就会注入到这个实例里面。。

MockBean和Mock的区别:MockBean会替代所有 上下文中所有相同类型的Mock.Mock只是模拟对象。
Mock和Spy的区别:Mock模拟的对象里面的方法,如果没有设备返回,那么都是返回null,spy的话如果没有设定其中的方法,那么走的就是真实对象里的方法。
Mock和InJectMock的区别:Controller层里面要调用Service层,那我Mock的是Service层的接口,那我去调用Controller层的时候,这个Mock的Service就要通过这个方式注入。

三.rest-assured
Rest-Assured是一个REStfulApi测试的利器,可以很方便的去测试自己的API。主要就是调用你自己Controller层来完成自己的测试。当然,它属于一个框架,如果你不喜欢用它,直接用MockMVC也是可以的,那你不继续往下看也是可以的。
我们先来看最基础的调用。
添加依赖:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--做测试用的-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <!--做测试用的-->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>3.3.0</version>
            <scope>test</scope>
        </dependency>

在JunitTest类中,添加静态依赖

io.restassured.RestAssured.*
io.restassured.matcher.RestAssuredMatchers.*
org.hamcrest.Matchers.*

这里也加上了json数据的使用方法.

 @Test
    void userMessage() {
        Base_User_R x = new Base_User_R();
        x.setA("a");
       x.setO("o");
       //这里将模拟http请求发送json数据到APi接口
        given().contentType("application/json").body(x).log().all().
                when().post("http://localhost:8088/Get/User/Message").//输出到接口
                then().
                assertThat().body("data.age", equalTo(18)).//断言判断返回的json中data:{age:""}是否等于18
                assertThat().body("data.name", equalTo("louki")).
                assertThat().body("code",equalTo(200));
                }

这里只做实例,其它方法就暂时先不放出来。执行后,根据log,可以看到方法执行的是否正常。

四.restassuredMvc和Mock

最重要的来了!!!
这是我们的Controller层

   public class TestController{
   //路径映射,对应浏览器访问的地址,访问该路径则执行下面函数
    @RequestMapping("/hello1")
    @ResponseBody
    public String hello1() {
        return gTestServer.he();
    }

这是Service层

public class TestServer {
   public String he(){
        return "hehehehee";
    }

}

如果你直接使用rest-assured,然后使用Mock去模拟了一个方法的返回。我一开始认为,这样是没什么问题的,毕竟。我Mock了Service中的调用。但是显而易见,悲剧是一定会发生的。

   @MockBean
    TestServer testServer;

 void userMessage2() throws RetException {
        Base_User_R x = new Base_User_R();
        x.setA("a");
        x.setO("o");
        x.setUseraccount("louki_test");

        //这个是隔离服务的.当调用control的这个方法且,x为这样的时候,返回。。
        Mockito.when(testServer.he()).thenReturn("ReTurnValue");

        System.out.println(testServer.he());
        RestAssured.given().
                contentType("application/json").body(x).log().all().
                when().post("/hello1").
                then().log().all().
                assertThat().body(containsString("ReTurnValue"));

    }

根据log可以看出,在调用Service.he方法时,确实已经根据我们设置的返回,返回的是"ReTurnValue"。但是在Rest-Assured却没有调用Mock中的方法
在这里插入图片描述
在这里插入图片描述
后面我看到,Mockito一般是搭配着MockMVC去做Api的测试,那Rest-Assured里面也是继承了MockMVC的,那我就开始尝试Rest_AssuredMVC去搭配MockMVC的去使用。
依赖不变,Controller,Service层不变。
我们改变使用的是RestAssuredMockMvc中given方法.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class Get_UserControlTest {

    @MockBean
    TestServer testServer;
	
	//这两个注解很重要,如果不加,也是造成同样的结果.
	//Autowired不加,则造成空指针
    @InjectMocks
    @Autowired
    TestController xxx;
    
    @Test
    void userMessage() throws RetException {
        Base_User_R x = new Base_User_R();
        x.setA("a");
        x.setO("o");
        x.setUseraccount("louki_test");

        //这个是隔离服务的.当调用control的这个方法且,x为这样的时候,返回。。
        Mockito.when(testServer.he()).thenReturn("ReTurnValue");

        System.out.println(testServer.he());
        RestAssuredMockMvc.given().standaloneSetup(xxx).
                contentType("application/json").body(x).log().all().
        when().post("/hello1").
        then().log().all().
        assertThat().body(containsString("ReTurnValue"));

    }

}

运行结果,皆大欢喜。
在这里插入图片描述
这里需要注意的是,Control层需要用@InjectMocks进行注解。而我们模拟Mock的Service层需要用@Mock注解。这样就把我们模拟的Mock注入到我们调用的Restassured中
这中间真的尝试了很多方法,有好多坑。而且我发现没有放在一起用的,只能靠自己一步一步摸索,在此记录一下,如果对你有用的,可以点一个小小赞~谢谢。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值