JUnit测试进阶(Mock测试)


一、Mock测试

1.Mock测试产生背景

一个应用程序通常由多个类文件组成,各个类之间彼此存在着继承,实现,关联,依赖等关系,共同为用户服务。应用中单个类文件通常不能看作一个单独的个体,它可能被某个类使用,也可能使用其他类。因此,要想对应用开展充分的测试,应当充分考虑每个类的上下文环境。然而,在应用开发时其所以依赖的功能和模块总是不完整的。例如,应用程序需要通过HTTP连接获得第三方服务器或数据库提供的服务,但在开发初期尚不存在可用的服务器或数据库,此时需要相应的功能模拟。又如,某个开发者所负责的模块功能依赖于其他开发者尚未完成的模块,在测试也需要模拟这些模块的功能。对于上述情形,开发者需要通过Mock测试来保证测试的有效性


2.什么是Mock测试

Mock测试在对程序模块进行测试时,通过替换与待测方法协作的对象,来实现待测代码与其他代码的隔离。值得注意的是,Mock只为测试提供服务,因此替换模块并不需要实现任何程序逻辑,只提供一个用于模仿被替换方法的空客


3.具体案例

下面以类Account,Manager和Service 为例说明Mock的测试方法,如图1和图2所示。其中Account表示账户,Manager负责将数据持久化到数据库,Service提供账户相关的服务(其transfer方法负责转账功能)。由于Service类涉及了账目金额的相关管理,因此需要为其建立一个数据库并预先加入测试数据。在上线运行时,对Service进行测试是非常方便的,然而在单元测试时,为其单独建一个数据库,设计测试数据便显得比较复杂,对此。可以用Mock对象来模拟所需的功能和数据,提高单元测试效率


图1
(类Account)


在这里插入图片描述
(接口Manager)


以Service的方法为例,该方法实现了转款人sender 对收款人beneficiary的转账功能,具体转账操作则是通过Manager完成:首先,根据转款人和收款人的ID获取他们的账户,其次,根据转款金额对转款人的账户金额运行自减操作,对收款人的账户余额进行自增操作;最后,更新收款人和转款人的数据库信息,从而实现转账操作。可以看到,负责与数据库交互的Manager类是整个程序的关键


对transfer方法进行测试时,一方面需要实现Manager接口,与Service提高服务,另一方面,在实现Manager接口的同时也需要构建数据库,并于数据库建立连接,然而,为了测试transfer方法而实现Manager接口,构建数据库是十分复杂的,对此,可通过Mock测试来模拟Manager的功能,只须满足transfer所需的功能即可。此外,通过Mock测试还可以实现transfer与Manager的隔离,使测试者更关注于transfer中的缺陷


在这里插入图片描述
(服务Service)


下图给出了测试类MockManager和ServiceTest。其中,MockManager并未真正与数据库建立连接,而是实现了Service所需的功能(包括addAccount,findAccountForUser,
updateAccount等功能),也因而实现Manager 与Service的隔离


在这里插入图片描述
(测试类MockManager)


注:下图是最终测试

在这里插入图片描述
可以看到最后的测试成功,Mock测试成功!

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Mock是一种模拟对象,用于在单元测试中替代真实对象的行为,以便测试代码的正确性。Junit可以与Mock框架一起使用,以便在单元测试中创建和使用Mock对象。 下面是一个使用Mockito框架进行mock测试的例子: 假设我们有一个UserService类,其中包含一个getUserById方法,该方法返回一个User对象,我们可以使用Mockito框架来创建一个模拟的UserService类,并模拟getUserById方法的返回值。 ```java public class UserServiceTest { @Mock private UserService userService; @Before public void setUp() { MockitoAnnotations.initMocks(this); } @Test public void testGetUserById() { User user = new User(); user.setId(1); user.setName("Alice"); when(userService.getUserById(1)).thenReturn(user); // 调用userService的getUserById方法 User result = userService.getUserById(1); // 验证getUserById方法被调用过一次 verify(userService, times(1)).getUserById(1); // 验证返回的User对象的属性值是否正确 assertEquals(1, result.getId()); assertEquals("Alice", result.getName()); } } ``` 在这个例子中,我们使用@Mock注解来创建一个模拟的UserService类,并使用MockitoAnnotations.initMocks(this)方法来初始化Mockito框架。然后,我们使用when(userService.getUserById(1)).thenReturn(user)来定义getUserById方法的返回值。最后,我们调用userService的getUserById方法,并使用verify(userService, times(1)).getUserById(1)来验证getUserById方法被调用过一次。 总的来说,Mockito框架提供了丰富的API来创建和管理Mock对象,帮助我们编写更高质量的单元测试

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大猪猪吃虎虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值