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

网站开发制作公司简介公众号编辑器小蚂蚁

网站开发制作公司简介,公众号编辑器小蚂蚁,电脑学堂网页制作,html做调查问卷网站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://wiki.neutronadmin.com/news/71945/

相关文章:

  • 学做预算有网站吗芜湖网站建设优化
  • 做网站聊城企业形象网站解决方案
  • 南通网站开发招聘网站建设 中企动力东莞后台管理
  • 泉州市做网站优化万网域名交易
  • 重庆科技网站设计模板智能营销型网站
  • 河北建设网站首页手表网站上没有价格
  • 北京建站开发asp.net构建门户网站
  • 怎样在谷歌做网站优化大师apk
  • 合肥做网站排名最简单网站建设
  • 网站三大标签手机介绍网站
  • 淘宝网站设计模板下载百度竞价推广怎么收费
  • 微信公众平台官方网站登录互动教学平台
  • 网站开发培训程序员网站算信息化建设
  • 太仓网站公司wordpress主题学习
  • 做网站老板不发工资我拿尾款十九冶成都建设网站
  • 怎么做好网站建设wordpress带投稿模板
  • 张家界城乡建设网站山东浩景建设有限公司网站
  • 经营网站 备案信息管理系统商城网站建设专业公司
  • 鲜花店网站页面-欧美模板1psd重庆市安全建设工程信息
  • 正规代做毕业设计的网站做电商网站都需要学什么软件
  • 兰州网站公司python用于网站开发
  • 南通建设工程造价信息网站德州网站制作
  • 改图网网站谁做的wordpress设置多域名多站点
  • 百度推广送企业网站吗网站设计制作公司大全
  • nodejs做企业网站seo收录查询
  • 网站建设规划方案制作上饶商城网站建设
  • 山西网站seo广州平面设计工作室
  • jsp网站开发遇到的问题市场推广方案和思路
  • 网站建设捌金手指花总十六网站正在建设模板
  • 美橙西安网站备案拍照服装网站技术解决方案