@Test Mock数据的单元测试

3 篇文章 0 订阅
3 篇文章 0 订阅

开发中经常用到单元测试,但有的逻辑代码涉及到数据库操作,当然,在测试的时候可以连接数据库测试,但有一些特殊情况是不能让工程编译的时候连接数据库的,这个时候单元测试就会出问题。于是,在不是主要测试数据库的逻辑单元测试的时候,就可以用单元测试中的Mock功能来模拟数据,从而测试逻辑代码结构是否完整,是否可以用某些特定的参数得到相应的结果。

简单的说就是:通过模拟数据进行各类的单元测试

go

首先构建一个bean,这就是我们接下来要操作的数据了:

public class DemoData {
    private String dataName;
    private String dataInfo;

    public String getDataName() {
        return dataName;
    }

    public void setDataName(String dataName) {
        this.dataName = dataName;
    }

    public String getDataInfo() {
        return dataInfo;
    }

    public void setDataInfo(String dataInfo) {
        this.dataInfo = dataInfo;
    }
}

其次,是操作这个数据源的数据库连接类(dao)

public interface DemoDataDao {
    /**
     * 通过传入的值返回相应数量的数据集
     * @param number 需要返回数据的数量
     * @return 和传入值相同数量的数据集
     */
    List<DemoData> getSomeData(int number);
}

接下来是数据管理类接口(service)

public interface testService {
    /**
     * 获取部分数据
     * @param number 需要获取的数据量
     * @return 相应数据量的数据集
     */
    List<DemoData> getSomeData(int number);
}

实现当前接口

@Component
public class TestServiceImpl implements testService {

    @Autowired
    private DemoDataDao demoDataDao;

    @Override
    public List<DemoData> getSomeData(int number){
        return demoDataDao.getSomeData(number);
    }
}

最后是控制类(Controller)

@RestController
@RequestMapping("/demo")
@EnableAutoConfiguration
public class TestController {

   @Autowired
   private testService service;

   private static Integer flagNumber = 5;

   @RequestMapping(value = "/test",method = RequestMethod.POST)
   public List<DemoData> test(@RequestBody int number){
       if(number > flagNumber){
           return null;
       }else{
           return service.getSomeData(number);
       }
   }
}

好了,背景交代完毕,接下来开始构建测试类

===============================这=是=一=条=分=割=线=================================

首先,在工程的pom文件中添加对于mock数据的依赖

<!-- testNG测试类和Mock依赖 -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <scope>test</scope>
        </dependency>

对于某个类的测试类生成,

IDEA的快捷键是  ctrl+shift+t  --> create new test

选择JUnit4 并 勾上你要测试的方法 确定之后就会在当前工程目录下创建出一个test类

 首先 @InjectMocks算是声明出要进行模拟数据的测试类,@Mock 就是声明当前测试类中需要模拟数据的接口。举例,就像我们现在用到的这个例子,在TestController中有用到testService这个接口的数据,那么就@Mock出这个接口,如果在这个Controller中用到了其他的service,就mock出其他的service就行了

    /**
     * 构建测试对象
     */
    @InjectMocks
    private TestController controller;

    /**
     * Mock出数据构建类
     */
    @Mock
    private testService service;

以下为整个测试类的完整代码,具体操作意义见注释

public class TestControllerTest {

    /**
     * 构建测试对象
     */
    @InjectMocks
    private TestController controller;

    /**
     * Mock出数据构建类
     */
    @Mock
    private testService service;

    @BeforeClass
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    /**
     * 构建初始化参数
     */
    Integer number = 1;

    @BeforeMethod
    public void createData() {
        number = 1;
    }

    @Test
    public void testTest1() {
        //当service中的getSomeData的参数为1的时候,则返回getData方法参数为1的数据
        when(service.getSomeData(1)).thenReturn(getData(1));
        //开始测试controller中的test方法,并返回结果
        List<DemoData> list = controller.test(number);
        //构建期望值(也就是告诉程序结果应该是个什么样子)
        List<DemoData> list1 = getData(1);
        //给当前测试下断言(结果值与期望值对比)
        Assert.assertEquals(list.size(),list1.size());
    }

    /**
     * 构建模型数据
     * @param number 需要返回的数据条数
     * @return 返回相应条数的数据
     */
    private List<DemoData> getData(Integer number){
        List<DemoData> list = new ArrayList<>();
        for(int run=0;run<number;run++){
            DemoData data = new DemoData();
            data.setDataName("name"+run);
            data.setDataInfo("info"+run);
            list.add(data);
        }
        return list;
    }

}

点击测试:

结果如下:

测试成功 

2018/12/25  更新知识点:


 对于@value注入到类中的属性,可以通过

ReflectionTestUtils.setField 进行注入

例如以上例子中:

@RestController
@RequestMapping("/demo")
@EnableAutoConfiguration
public class TestController {

   @Autowired
   private testService service;
    
   //将如下参数以@Value从配置文件中注入(具体方式见SpringBoot中的@Value)
   //private static Integer flagNumber = 5;
   @Value("flagNumber")
   Integer flagNumber;

   @RequestMapping(value = "/test",method = RequestMethod.POST)
   public List<DemoData> test(@RequestBody int number){
       if(number > flagNumber){
           return null;
       }else{
           return service.getSomeData(number);
       }
   }
}

 那么,在测试类中就可以通过

@Test
    public void testTest1() {
        ReflectionTestUtils.setField(controller, "flagNumber", 4);
        //当service中的getSomeData的参数为1的时候,则返回getData方法参数为1的数据
        when(service.getSomeData(1)).thenReturn(getData(1));
        //开始测试controller中的test方法,并返回结果
        List<DemoData> list = controller.test(number);
        //构建期望值(也就是告诉程序结果应该是个什么样子)
        List<DemoData> list1 = getData(1);
        //给当前测试下断言(结果值与期望值对比)
        Assert.assertEquals(list.size(),list1.size());
    }

中的“ReflectionTestUtils.setField(controller, "flagNumber", 4);”这段代码实现注入

2021/08/17  更新知识点:

对于未知的结果影响不大的方法,可以用这样的方式 在任何参数的形式下都返回相同结果

//模拟任何参数都返回 说明:
//makeGasStationHomeCountVO()  此方法为返回值构建方法
//gasSelectMapper 主要的dao类或者mapper类
//getGasStationHomeBaseCountVO(any(),any()) dao类中的具体方法, any() 代表任何参数 
      Mockito.doReturn(makeGasStationHomeCountVO()).when(gasSelectMapper).getGasStationHomeBaseCountVO(any(),any());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值