zoukankan      html  css  js  c++  java
  • .NET Core之单元测试(三):Mock框架Moq的使用

    编写一个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));
    }
    
    • 测试结果
      在这里插入图片描述
  • 相关阅读:
    面试必备的数据库悲观锁与乐观锁
    5分钟带你读懂事务隔离性与隔离级别
    带你了解数据库中事务的ACID特性
    带你了解数据库中group by的用法
    带你了解数据库中JOIN的用法
    一篇带你读懂TCP之“滑动窗口”协议
    通过“表白”的方式,让我们快速了解网络协议
    聊一聊Iterable与Iterator的那些事!
    一篇让你明白进程与线程之间的区别与联系
    MySQL 索引的增删查
  • 原文地址:https://www.cnblogs.com/zhaobingwang/p/12354045.html
Copyright © 2011-2022 走看看