单元测试-mock使用应该注意什么

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CSDN___LYY/article/details/86543667

系列导航

点击跳转到系列博文目录导航

概念

Mock的概念,其实很简单:所谓的mock就是创建一个类的虚假的对象,在测试环境中,用来替换掉真实的对象,以达到两大目的:

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

上述两大目的应该好好理解一下,理解了目的也就大致知道了何时使用mock

使用场景

  • 被测试对象依赖的对象构造复杂

比如:class A 依赖 class B、class B 依赖 class C和class D、class C 依赖 …、class D 依赖 …
此处我们想测试classA,在没有mock的情况下就要去根据要求去构造classBCD等对象,耗时耗力。
在mock的情况下,我们可以直接mockclassBCD并通过设计其行为来实现测试classA的目的,因为我们只是想测试class A的行为是否符合预期,我们并不需要测试依赖对象。

  • 被测试单元所依赖的模块还没有开发完成,而被测试对象需要需要依赖模块的返回值进行测试。也就是测试单元依赖了无法获取的下游数据

比如:service中方法的测试需要dao中的访问数据库操作并获取其返回值,但是我们还没有开发完成对应的dao方法,我们就可以mock一个dao层的对象,将其行为设置为:当调用其中的某个方法时返回一个设定的值。
这样我们对service的测试就可以不必受dao层的开发速度影响。也符合只对service方法逻辑进行测试。

原则

  • 不需要对所有的单元测试都将对象进行mock,只对上述使用场景介绍的相关场景使用mock。
  • 在分层测试中,高层的测试设计可以基于以下假设:底层的测试已保证底层对象的质量,高层无需关心低层对象的内部逻辑质量。这种情况下高层可以对低层对象进行mock。

常用框架

  • EasyMock : 早期比较流行的mock框架,它提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock 对象返回指定的值或抛出指定异常
  • Mockito:EasyMock之后流行的mock工具。相对EasyMock学习成本低,而且具有非常简洁的API,测试代码的可读性很高。
  • PowerMock:这个工具是在EasyMock和Mockito上扩展出来的,目的是为了解决EasyMock和Mockito不能解决的问题,比如对static, final, private方法均不能mock。

其实测试架构设计良好的代码,一般并不需要这些功能,但如果是在已有项目上增加单元测试,老代码有问题且不能改时,就不得不使用这些功能了。
PowerMock 在扩展功能时完全采用和被扩展的框架相同的 API, 熟悉 PowerMock 所支持的模拟框架的开发者会发现 PowerMock 非常容易上手。PowerMock 的目的就是在当前已经被大家所熟悉的接口上通过添加极少的方法和注释来实现额外的功能。目前PowerMock 仅扩展了 EasyMock 和 mockito,需要和EasyMock或Mockito配合一起使用。

  • Jmockit:JMockit 是一个轻量级的mock框架是用以帮助开发人员编写测试程序的一组工具和API,该项目完全基于 Java 5 SE 的 java.lang.instrument 包开发,内部使用 ASM 库来修改Java的Bytecode。

Jmockit功能和PowerMock类似,某些功能甚至更为强大,但个人感觉其代码的可读性并不强。

mock框架有好多,我们在选用mock框架时可以根据使用环境使用相对的mock框架,不过在正常情况下,个人感觉mockito还是不错的:代码可读性强,易于上手,功能绝大数项目的单元测试都够用,不需要依赖其他组件。这或许也是mockito这么流行的原因吧。

refer:博客 博客

如果转载此博文,请附上本文链接,谢谢合作~ :https://blog.csdn.net/csdn___lyy

如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!

展开阅读全文

ASP.NET MVC4 Mock单元测试

09-28

第一次使用mock单元测试,但是总是抛出空引用的异常:请各位大牛们给看看啥问题:rn接口文件:rnpublic interface IUserRepositoryrn rn IQueryable Users get; rn OperateResult SignIn(User user);rn rn实现接口类的文件:rnpublic class UserRepository : IUserRepositoryrn rn public OperateResult SignIn(User user)rn rn var result = new OperateResultrn rn Success = Users.Any(u => u.UserName == user.UserName && u.Password == user.Password)rn ;rn if (!result.Success)rn rn result.Message = "错误的用户名或密码.";rn rn return result;rn rn public IQueryable Usersrn rn get throw new NotImplementedException(); rn rn rnrn测试方法类:rn [TestClass]rn public class UserTestrn rn [TestMethod]rn public void UserSingInTest()rn rn var user1 = new User UserId = 1, UserName = "jli@synvata.com", Password = "241925";rn var user2 = new User UserId = 2, UserName = "junelee1211@qq.com", Password = "000000";rnrn var mock = new Mock();rn mock.Setup(u => u.Users).Returns(new Listrn rn user1,rn user2rn .AsQueryable());rnrn var result1 = mock.Object.SignIn(new User UserId = 1, UserName = "jli@synvata.com", Password = "241925" );rn var result2 = mock.Object.SignIn(new User UserId = 2, UserName = "jli", Password = "241925" );rn Assert.IsTrue(result1.Success);rn Assert.IsFalse(result1.Success);rn Assert.AreEqual(string.Empty, result1.Message);rn Assert.AreEqual("错误的用户名或密码.", result2.Message);rn rn rnrn运行测试总是会提示:rnAn exception of type 'System.NullReferenceException' occurred in DBPortal.Tests.dll but was not handled in user codernrnAdditional information: 未将对象引用设置到对象的实例。rnrn我猜猜原因可能就是UserRepository 类的Users引起的,可是想不明白的是我已经在测试类中给它添加虚假的值了啊。诸位给指点下是啥原因啊rnrn 论坛

没有更多推荐了,返回首页