新增一個接口git
public interface IFoo { bool Ping(string ip); }
接口實現github
public class Foo : IFoo { public bool Ping(string ip) { return new Random().Next(1, 100) % 2 == 1; } }
編寫一個待測試的API,其中有三個依賴項:SqliteDbContext
,ILogger<SampleController>
和IFoo
API實現的功能:先獲取SqliteDbContext中的SampleEntity,若是其中的屬性StringValue值爲ping,而且結果爲False,則返回404
,不然返回SampleEntitysql
[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; _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); } }
ILogger<SampleController>
var loggerMock = new Mock<ILogger<SampleController>>(); var logger = loggerMock.Object;
Ping(string ip)
var fooMock = new Mock<IFoo>(); fooMock.Setup(foo => foo.Ping("localhost")).Returns(true); var foo = fooMock.Object;
關於
Moq
的更多操做可參見:Moq4 Quickstartapi
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)); }