当前位置: 首页 > news >正文

免费建立国外网站服务器平台

免费建立国外网站,服务器平台,短链接生成器app,泰州做房产的网站Mock 框架 Moq 的使用IntroMoq 是 .NET 中一个很流行的 Mock 框架#xff0c;使用 Mock 框架我们可以只针对我们关注的代码进行测试#xff0c;对于依赖项使用 Mock 对象配置预期的依赖服务的行为。Moq 是基于 Castle 的动态代理来实现的#xff0c;基于动态代理技术动态生成… Mock 框架 Moq 的使用IntroMoq 是 .NET 中一个很流行的 Mock 框架使用 Mock 框架我们可以只针对我们关注的代码进行测试对于依赖项使用 Mock 对象配置预期的依赖服务的行为。Moq 是基于 Castle 的动态代理来实现的基于动态代理技术动态生成满足指定行为的类型在一个项目里, 我们经常需要把某一部分程序独立出来以便我们可以对这部分进行测试. 这就要求我们不要考虑项目其余部分的复杂性, 我们只想关注需要被测试的那部分. 这里就需要用到模拟(Mock)技术.因为, 请仔细看. 我们想要隔离测试的这部分代码对外部有一个或者多个依赖. 所以编写测试代码的时候, 我们需要提供这些依赖. 而针对隔离测试, 并不应该使用生产时用的依赖项, 所以我们使用模拟版本的依赖项, 这些模拟版依赖项只能用于测试时, 它们会使隔离更加容易.img绿色的是需要被测试的类,黄色是Mock的依赖项——引用自杨旭大佬的博文Prepare首先我们需要先准备一下用于测试的类和接口下面的示例都是基于下面定义的类和方法来做的public interface IUserIdProvider {string GetUserId(); } public class TestModel {public int Id { get; set; } } public interface IRepository {int Version { get; set; }int GetCount();Taskint GetCountAsync();TestModel GetById(int id);ListTestModel GetList();TResult GetResultTResult(string sql);int GetNumT();bool Delete(int id); }public class TestService {private readonly IRepository _repository;public TestService(IRepository repository){_repository  repository;}public int Version{get  _repository.Version;set  _repository.Version  value;}public ListTestModel GetList()  _repository.GetList();public TResult GetResultTResult(string sql)  _repository.GetResultTResult(sql);public int GetResult(string sql)  _repository.GetResultint(sql);public int GetNumT()  _repository.GetNumT();public int GetCount()  _repository.GetCount();public Taskint GetCountAsync()  _repository.GetCountAsync();public TestModel GetById(int id)  _repository.GetById(id);public bool Delete(TestModel model)  _repository.Delete(model.Id); } 我们要测试的类型就是类似 TestService 这样的而 IRepositoyTestModel 和 IUserIdProvider 是属于外部依赖Mock MethodGet Started通常我们使用 Moq 最常用的可能就是 Mock 一个方法了最简单的一个示例如下[Fact] public void BasicTest() {var userIdProviderMock  new MockIUserIdProvider();userIdProviderMock.Setup(x  x.GetUserId()).Returns(mock);Assert.Equal(mock, userIdProviderMock.Object.GetUserId()); } Match Arguments通常我们的方法很多是带有参数的在使用 Moq 的时候我们可以通过设置参数匹配为不同的参数返回不同的结果来看下面的这个例子[Fact] public void MethodParameterMatch() {var repositoryMock  new MockIRepository();repositoryMock.Setup(x  x.Delete(It.IsAnyint())).Returns(true);repositoryMock.Setup(x  x.GetById(It.Isint(_  _  0))).Returns((int id)  new TestModel(){Id  id});var service  new TestService(repositoryMock.Object);var deleted  service.Delete(new TestModel());Assert.True(deleted);var result  service.GetById(1);Assert.NotNull(result);Assert.Equal(1, result.Id);result  service.GetById(-1);Assert.Null(result);repositoryMock.Setup(x  x.GetById(It.Isint(_  _  0))).Returns(()  new TestModel(){Id  -1});result  service.GetById(0);Assert.NotNull(result);Assert.Equal(-1, result.Id); } 通过 It.IsAnyT 来表示匹配这个类型的所有值通过 It.IsT(ExpressionFuncbool) 来设置一个表达式来断言这个类型的值通过上面的例子我们可以看的出来设置返回值的时候可以直接设置一个固定的返回值也可以设置一个委托来返回一个值也可以根据方法的参数来动态配置返回结果Async Method现在很多地方都是在用异步方法Moq 设置异步方法有三种方式一起来看一下示例[Fact] public async Task AsyncMethod() {var repositoryMock  new MockIRepository();// Task.FromResultrepositoryMock.Setup(x  x.GetCountAsync()).Returns(Task.FromResult(10));// ReturnAsyncrepositoryMock.Setup(x  x.GetCountAsync()).ReturnsAsync(10);// Mock Result, start from 4.16repositoryMock.Setup(x  x.GetCountAsync().Result).Returns(10);var service  new TestService(repositoryMock.Object);var result  await service.GetCountAsync();Assert.True(result  0); } 还有一个方式也可以但是不推荐编译器也会给出一个警告就是下面这样repositoryMock.Setup(x  x.GetCountAsync()).Returns(async ()  10); Generic Type有些方法会是泛型方法对于泛型方法我们来看下面的示例[Fact] public void GenericType() {var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);repositoryMock.Setup(x  x.GetResultint(It.IsAnystring())).Returns(1);Assert.Equal(1, service.GetResult());repositoryMock.Setup(x  x.GetResultstring(It.IsAnystring())).Returns(test);Assert.Equal(test, service.GetResultstring()); }[Fact] public void GenericTypeMatch() {var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);repositoryMock.Setup(m  m.GetNumIt.IsAnyType()).Returns(-1);repositoryMock.Setup(m  m.GetNumIt.IsSubtypeTestModel()).Returns(0);repositoryMock.Setup(m  m.GetNumstring()).Returns(1);repositoryMock.Setup(m  m.GetNumint()).Returns(2);Assert.Equal(0, service.GetNumTestModel());Assert.Equal(1, service.GetNumstring());Assert.Equal(2, service.GetNumint());Assert.Equal(-1, service.GetNumbyte()); } 如果要 Mock 指定类型的数据可以直接指定泛型类型如上面的第一个测试用例如果要不同类型设置不同的结果一种是直接设置类型如果要指定某个类型或者某个类型的子类可以用 It.IsSubtypeT如果要指定值类型可以用 It.IsValueType如果要匹配所有类型则可以用 It.IsAnyTypeCallback我们在设置 Mock 行为的时候可以设置 callback 来模拟方法执行时的逻辑来看一下下面的示例[Fact] public void Callback() {var deletedIds  new Listint();var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);repositoryMock.Setup(x  x.Delete(It.IsAnyint())).Callback((int id) {deletedIds.Add(id);}).Returns(true);for (var i  0; i  10; i){service.Delete(new TestModel() { Id  i });}Assert.Equal(10, deletedIds.Count);for (var i  0; i  10; i){Assert.Equal(i, deletedIds[i]);} } Verification有时候我们会验证某个方法是否执行并不需要关注是否方法的返回值这时我们可以使用 Verification 验证某个方法是否被调用示例如下[Fact] public void Verification() {var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);service.Delete(new TestModel(){Id  1});repositoryMock.Verify(x  x.Delete(1));repositoryMock.Verify(x  x.Version, Times.Never());Assert.ThrowsMockException(()  repositoryMock.Verify(x  x.Delete(2))); } 如果方法没有被调用就会引发一个 MockException 异常verification failedVerification 也可以指定方法触发的次数比如repositoryMock.Verify(x x.Version, Times.Never);默认是 Times.AtLeastOnce可以指定具体次数 Times.Exactly(1) 或者指定一个范围 Times.Between(1,2, Range.Inclusive)Moq 也提供了一些比较方便的方法比如Times.Never()/Times.Once()/Times.AtLeaseOnce()/Times.AtMostOnce()/Times.AtLease(2)/Times.AtMost(2)Mock PropertyMoq 也可以 mock 属性property 的本质是方法加一个字段所以也可以用 Mock 方法的方式来 Mock 属性只是使用 Mock 方法的方式进行 Mock 属性的话后续修改属性值就不会引起属性值的变化了如果修改属性则要使用 SetupProperty 的方式来 Mock 属性具体可以参考下面的这个示例[Fact] public void Property() {var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);repositoryMock.Setup(x  x.Version).Returns(1);Assert.Equal(1, service.Version);service.Version  2;Assert.Equal(1, service.Version); }[Fact] public void PropertyTracking() {var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);repositoryMock.SetupProperty(x  x.Version, 1);Assert.Equal(1, service.Version);service.Version  2;Assert.Equal(2, service.Version); } Sequence我们可以通过 Sequence 来指定一个方法执行多次返回不同结果的效果看一下示例就明白了[Fact] public void Sequence() {var repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);repositoryMock.SetupSequence(x  x.GetCount()).Returns(1).Returns(2).Returns(3).Throws(new InvalidOperationException());Assert.Equal(1, service.GetCount());Assert.Equal(2, service.GetCount());Assert.Equal(3, service.GetCount());Assert.ThrowsInvalidOperationException(()  service.GetCount()); } 第一次调用返回值是1第二次是2第三次是3第四次是抛了一个 InvalidOperationExceptionLINQ to Mocks我们可以通过 Mock.Of 来实现类似 LINQ 的方式创建一个 mock 对象实例指定类型的实例如果对象比较深要 mock 的对象比较多使用这种方式可能会一定程度上简化自己的代码来看使用示例[Fact] public void MockLinq() {var services  Mock.OfIServiceProvider(sp sp.GetService(typeof(IRepository))  Mock.OfIRepository(r  r.Version  1) sp.GetService(typeof(IUserIdProvider))  Mock.OfIUserIdProvider(a  a.GetUserId()  test));Assert.Equal(1, services.ResolveServiceIRepository().Version);Assert.Equal(test, services.ResolveServiceIUserIdProvider().GetUserId()); } Mock Behavior默认的 Mock Behavior 是 Loose默认没有设置预期行为的时候不会抛异常会返回方法返回值类型的默认值或者空数组或者空枚举在声明 Mock 对象的时候可以指定 Behavior 为 Strict这样就是一个**真正**的 mock 对象没有设置预期行为的时候就会抛出异常示例如下[Fact] public void MockBehaviorTest() {// Make mock behave like a true Mock,// raising exceptions for anything that doesnt have a corresponding expectation: in Moq slang a Strict mock;// default behavior is Loose mock,// which never throws and returns default values or empty arrays, enumerable, etcvar repositoryMock  new MockIRepository();var service  new TestService(repositoryMock.Object);Assert.Equal(0, service.GetCount());Assert.Null(service.GetList());var arrayResult  repositoryMock.Object.GetArray();Assert.NotNull(arrayResult);Assert.Empty(arrayResult);repositoryMock  new MockIRepository(MockBehavior.Strict);Assert.ThrowsMockException(()  new TestService(repositoryMock.Object).GetCount()); } 使用 Strict 模式不设置预期行为的时候就会报异常异常信息类似下面这样strict exceptionMoreMoq 还有一些别的用法还支持事件的操作还有 Protected 成员的 Mock还有一些高级的用法自定义 Default 行为等感觉我们平时可能并不太常用所以上面并没有加以介绍有需要用的可以参考 Moq 的文档上述测试代码可以在 Github 获取 https://github.com/WeihanLi/SamplesInPractice/blob/master/XunitSample/MoqTest.csReferenceshttps://github.com/moq/moq4/wiki/Quickstarthttps://github.com/moq/moq4https://github.com/WeihanLi/SamplesInPractice/blob/master/XunitSample/MoqTest.cshttps://www.cnblogs.com/tylerzhou/p/11410337.htmlhttps://www.cnblogs.com/cgzl/p/9304567.htmlhttps://www.cnblogs.com/haogj/archive/2011/07/22/2113496.html
http://www.pierceye.com/news/233076/

相关文章:

  • php做的网站如何该样式云服务器产品介绍
  • 个人网站建设论文绪论上海it公司有哪些
  • 建设网站推广广告图郑州妇科医院哪家好些
  • 自己网站wordpress主题怎么wordpress 功能块
  • 网站制作咨询电话网站建设技术员分为前端 后端
  • 9元建站节建材 团购 网站怎么做
  • 河南城乡住房和建设厅网站公司微信网站建设方案模板下载
  • 西安制作公司网站的公司邯郸市三建建筑公司网址
  • 网站建设工作目标惠州网站网站建设
  • 就业创业网站建设微信app下载安装旧版本
  • 沧州网站备案年栾洪全单页做网站教程
  • 网站开发的疑虑做门窗投标网站
  • 小型企业门户网站源码如何使用wordpress制作网站
  • 深圳网络营销网站建设北京建设网证书查询平台官网
  • 广播电台网站建设板块自己做网站导航页
  • 网站ui设计兼职android开发工具箱
  • 网站导航网站开发建设公司自己的网站
  • 网站建设专业的公司哪家好优秀创意网站
  • wordpress 文件目录seo网站关键词排名软件
  • 网站管理员功能wordpress增加购物车
  • 外国广告公司网站一个wordpress的爱好者
  • 锦溪网站建设怎么查看网站是否被收录
  • 网站建设感悟平面设计在哪里接单
  • 网站建设中html网页软件开发定制外包服务商
  • 山东seo网站推广河南定制网站建设企业
  • 网站建设文献文档单产品网站建设
  • 唐山网站建设自主开发宁波北仑做公司网站
  • 廊坊网页模板建站专业网站建设公司排名
  • 广州本地生活appseo百度百科
  • 成都产品网站建设镜像网站是怎么做的