编写一个API

新增一个接口

public interface IFoo
{
bool Ping(string ip);
}

接口实现

public class Foo : IFoo
{
public bool Ping(string ip)
{
return new Random().Next(1, 100) % 2 == 1;
}
}

编写一个待测试的API,其中有三个依赖项:SqliteDbContextILogger<SampleController>IFoo

API实现的功能:先获取SqliteDbContext中的SampleEntity,如果其中的属性StringValue值为ping,并且结果为False,则返回404,否则返回SampleEntity

[Route("api/[controller]")]
[ApiController]
public class SampleController : ControllerBase
{
private readonly SqliteDbContext _sqliteDbContext;
private readonly ILogger<SampleController> _logger;
private readonly IFoo _foo;
public SampleController(SqliteDbContext sqliteDbContext, ILogger<SampleController> logger,IFoo foo)
{
_logger = logger;
_foo = foo;
_sqliteDbContext = sqliteDbContext;
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
var sampleData = await _sqliteDbContext.SampleEntity
.SingleOrDefaultAsync(s => s.Id == id);
if (sampleData?.StringValue == "ping")
{
var pingOk = _foo.Ping("localhost");
if (!pingOk)
return NotFound();
}
return Ok(sampleData);
}
}

测试用例

  • Mock ILogger<SampleController>
var loggerMock = new Mock<ILogger<SampleController>>();
var logger = loggerMock.Object;
  • Mock Ping(string ip)
var fooMock = new Mock<IFoo>();
fooMock.Setup(foo => foo.Ping("localhost")).Returns(true);
var foo = fooMock.Object;

关于Moq的更多操作可参见:Moq4 Quickstart

  • 修改GetSqliteDbContextAsync(),新增一个ID为2的数据记录
private async Task<SqliteDbContext> GetSqliteDbContextAsync()
{
var options = new DbContextOptionsBuilder<SqliteDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var sqliteDbContext = new SqliteDbContext(options);
sqliteDbContext.SampleEntity.Add(new Infrastructure.Entities.SampleEntity
{
Id = 1,
BoolValue = false,
DateTimeValue = DateTime.Now,
StringValue = "sample"
}); sqliteDbContext.SampleEntity.Add(new Infrastructure.Entities.SampleEntity
{
Id = 2,
BoolValue = false,
DateTimeValue = DateTime.Now,
StringValue = "ping"
});
await sqliteDbContext.SaveChangesAsync();
return sqliteDbContext;
}
  • 测试Ping==True
[TestMethod]
public async Task Get_ReturnOK_WithPingTrue()
{
// Arrange
var dbContext = await GetSqliteDbContextAsync(); var loggerMock = new Mock<ILogger<SampleController>>();
var logger = loggerMock.Object; var fooMock = new Mock<IFoo>();
fooMock.Setup(foo => foo.Ping("localhost")).Returns(true);
var foo = fooMock.Object; var controller = new SampleController(dbContext, logger, foo); // Act
var response = await controller.Get(2);
var responseModel = ((OkObjectResult)response).Value as SampleEntity; // Assert
Assert.IsInstanceOfType(response, typeof(OkObjectResult));
Assert.IsTrue(responseModel.Id == 2);
Assert.IsFalse(responseModel.BoolValue);
Assert.IsTrue(responseModel.StringValue == "ping");
}
  • 测试Ping==False
[TestMethod]
public async Task Get_ReturnOK_WithPingFalse()
{
// Arrange
var dbContext = await GetSqliteDbContextAsync(); var loggerMock = new Mock<ILogger<SampleController>>();
var logger = loggerMock.Object; var fooMock = new Mock<IFoo>();
fooMock.Setup(foo => foo.Ping("localhost")).Returns(false);
var foo = fooMock.Object; var controller = new SampleController(dbContext, logger, foo); // Act
var response = await controller.Get(2); // Assert
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
}
  • 测试结果

.NET Core之单元测试(三):Mock框架Moq的使用的更多相关文章

  1. Mock 框架 Moq 的使用

    Mock 框架 Moq 的使用 Intro Moq 是 .NET 中一个很流行的 Mock 框架,使用 Mock 框架我们可以只针对我们关注的代码进行测试,对于依赖项使用 Mock 对象配置预期的依赖 ...

  2. 教育单元测试mock框架优化之路(上)

    转载:https://sq.163yun.com/blog/article/169561874192850944 众所周知,mock对于单元测试,尤其是基于spring容器的单元测试,是非常重要的.它 ...

  3. MoQ(基于.net3.5,c#3.0的mock框架)简单介绍

    我们在做单元测试的时候,常常困扰于数据的持久化问题,很多情况下我们不希望单元测试影响到数据库中的内容,而且受数据库的影响有时我们的单元测试的速度会很慢,所以我们往往希望将持久化部分隔离开,做单元测试的 ...

  4. 教育单元测试mock框架优化之路(中)

    转载:https://sq.163yun.com/blog/article/169564470918451200 三.间接依赖的bean的mock替换 对于前面提供的@Mock,@Spy+@Injec ...

  5. 单元测试mock框架——jmockit实战

    JMockit是google code上面的一个java单元测试mock项目,她很方便地让你对单元测试中的final类,静态方法,构造方法进行mock,功能强大.项目地址在:http://jmocki ...

  6. .Net Core的简单单元测试基于Mock和自定义

    首先创建 使用mock 外部依赖一般用Mock 模拟 下载包 例如 3.1:首先先要使用MOCk来模拟测试方法需要的参数,这一步为 Arrange; 简单的模拟 var mock = new Mock ...

  7. 教育单元测试mock框架优化之路(下)

    转载:https://sq.163yun.com/blog/article/169563599967031296 四.循环依赖的解决 果然! 当我将@SpyBean应用到存在有循环依赖的Bean上时, ...

  8. Net Core WebApi单元测试

    单元测试 本篇将结合这个系列的例子的基础上演示在Asp.Net Core里如何使用XUnit结合Moq进行单元测试,同时对整个项目进行集成测试. 第一部分.XUnit 修改 Project.json  ...

  9. .NET 单元测试的利剑——模拟框架Moq(简述篇)

    .NET 单元测试的利剑--模拟框架Moq 前言 这篇文章是翻译文,因为通过自己参与的项目,越发觉得单元测试的重要性,特别是当跟业务数据打交道的时候的,Moq就如雪中送炭,所以想学习这个框架,就从这篇 ...

随机推荐

  1. Spring Boot2 系列教程 (十三) | 整合 MyBatis (XML 版)

    前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,之前介绍过了 SpringBoot 整合MyBatis 注解版的使用,上一篇介绍过 MyBatis ...

  2. Hive 这些基础知识,你忘记了吗?

    Hive 其实是一个客户端,类似于navcat.plsql 这种,不同的是Hive 是读取 HDFS 上的数据,作为离线查询使用,离线就意味着速度很慢,有可能跑一个任务需要几个小时甚至更长时间都有可能 ...

  3. C++读书笔记

    C与C++的不同点 C++在struct,union中定义的函数叫成员函数,在class中定义的数据叫数据成员 C++引入了三个存取权限的关键字:public,protected,private pu ...

  4. 如何清理 Docker 占用的磁盘空间

    Docker 很占用空间,每当我们运行容器.拉取镜像.部署应用.构建自己的镜像时,我们的磁盘空间会被大量占用. 如果你也被这个问题所困扰,咱们就一起看一下 Docker 是如何使用磁盘空间的,以及如何 ...

  5. 缓存读写策略 - Cache Aside.md

    场景描述 比如一条数据同时存在数据库.缓存,现在你要更新此数据,你会怎么更新? 先更新数据库?还是先更新缓存? 其实这两种方式都有问题. (1)先更新数据库,后更新缓存 这样会造成数据不一致. A 先 ...

  6. C#中TripleDES对应Java中的DESede即大家说的3DES,附C#及Java加解密结果一致的控制台程序例子

    直接上代码了. Java控制台代码: package Test; import java.security.Key; import javax.crypto.Cipher; import javax. ...

  7. Docker安装之路

    从3月初到现在,一直在安装docker 的路上越走越远,大概就在1个小时前,我终于成功了,那一刻,我觉得我拥有了整个世界,于是乎,拥有了整个世界的我决定草率的并粗略的记录一下安装过程中遇到的我能记住的 ...

  8. 【WPF学习】第十九章 控件类

    WPF窗口充满了各种元素,但这些元素中只有一部分是控件.在WPF领域,控件通常被描述为与用户交互的元素——能接收焦点并接受键盘或鼠标输入的元素.明显的例子包括文本框和按钮.然而,这个区别有时有些模糊. ...

  9. 软工造梦厂团队项目(Alpha版本发布2)

    课程 (https://edu.cnblogs.com/campus/xnsy/GeographicInformationScience) 作业要求 https://www.cnblogs.com/h ...

  10. python多层数组合成一个数组后循环打印出数组内的每一项元素的方法

    a=[1,2,3,4] b=[5,6,7,8] c=[a,b] def test(c): for i in c: return i print(test(c)) 以上代码执行后打印出来的结果是 预期目 ...