编写一个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. .NET为什么要使用异步(async)编程?⭐⭐⭐⭐⭐

    .NET为什么要使用异步(async)编程? 有几点坐下笔记 ⭐⭐⭐⭐: 1. 同步方法 static void Main(string[] args) { Console.WriteLine($&q ...

  2. crawler碎碎念4 关于python requests、Beautiful Soup库、SQLlite的基本操作

    Requests import requests from PIL import Image from io improt BytesTO import jason url = "..... ...

  3. python StringIO和ByteIO

    一.StringIO 1.作用:在内存在读写str # 导入模块 from io import StringIO # 实例化StringIO对象 str_io = StringIO() # 向内存中写 ...

  4. JS前端时间格式化

    var dateTime = new Date(tree_time); tree_time = dateTime.getFullYear() + '-'+ (dateTime.getMonth()+1 ...

  5. 定义可选URL片段 定义自定义片段变量 精通ASP-NET-MVC-5-弗瑞曼

  6. Creating Form Elements --Using BeginForm and EndForm 使用内建的Form辅助器方法 精通ASP.NET MVC 5

    Using the BeginForm and EndForm Helper Methods in the CreatePerson.cshtml File

  7. 创建一个区域(Creating an Area) |使用区域 | 高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼

    摘自:http://www.cnblogs.com/chenboyi081/p/4472709.html#tar2015050302 下面的AdminAreaRegistration继承自AreaRe ...

  8. 深入理解大数据之——事务及其ACID特性

    目录 事务简介 事物的定义 事务的目的 事务的状态 事务的ACID属性 ACID简介 原子性(Atomicity) 一致性(Consistency) 隔离性(Isolation) 持久性(Durabi ...

  9. golang中基本类型存储大小和转换

    Go语言的基本类型有: bool string int.int8.int16.int32.int64 uint.uint8.uint16.uint32.uint64.uintptr byte // u ...

  10. java获取本地IP地址集合包括虚拟机的ip

    public static ArrayList<String> getLocalIpAddr() { ArrayList<String> ipList = new ArrayL ...