我对单元测试完全陌生,希望为我的控制器编写单元测试下面使用xunit和moq。我了解您只能模拟数据库事务,并且使单元测试独立于数据库。我该如何为这些编写xunit测试?任何文档或示例代码将不胜感激。我知道如何将xnit测试项目添加到我的解决方案中。
using System;
using System.Threading.Tasks;
using CoreServices.Models;
using CoreServices.Repository;
using Microsoft.AspNetCore.Mvc;
namespace CoreServices.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PostController : ControllerBase
{
IPostRepository postRepository;
public PostController(IPostRepository _postRepository)
{
postRepository = _postRepository;
}
[HttpGet]
[Route("GetCategories")]
public async Task<IActionResult> GetCategories()
{
try
{
var categories = await postRepository.GetCategories();
if (categories == null)
{
return NotFound();
}
return Ok(categories);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpGet]
[Route("GetPosts")]
public async Task<IActionResult> GetPosts()
{
try
{
var posts = await postRepository.GetPosts();
if (posts == null)
{
return NotFound();
}
return Ok(posts);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpGet]
[Route("GetPost")]
public async Task<IActionResult> GetPost(int? postId)
{
if (postId == null)
{
return BadRequest();
}
try
{
var post = await postRepository.GetPost(postId);
if (post == null)
{
return NotFound();
}
return Ok(post);
}
catch (Exception)
{
return BadRequest();
}
}
[HttpPost]
[Route("AddPost")]
public async Task<IActionResult> AddPost([FromBody]Post model)
{
if (ModelState.IsValid)
{
try
{
var postId = await postRepository.AddPost(model);
if (postId > 0)
{
return Ok(postId);
}
else
{
return NotFound();
}
}
catch (Exception)
{
return BadRequest();
}
}
return BadRequest();
}
[HttpPost]
[Route("DeletePost")]
public async Task<IActionResult> DeletePost(int? postId)
{
int result = 0;
if (postId == null)
{
return BadRequest();
}
try
{
result = await postRepository.DeletePost(postId);
if (result == 0)
{
return NotFound();
}
return Ok();
}
catch (Exception)
{
return BadRequest();
}
}
[HttpPost]
[Route("UpdatePost")]
public async Task<IActionResult> UpdatePost([FromBody]Post model)
{
if (ModelState.IsValid)
{
try
{
await postRepository.UpdatePost(model);
return Ok();
}
catch (Exception ex)
{
if (ex.GetType().FullName == "Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException")
{
return NotFound();
}
return BadRequest();
}
}
return BadRequest();
}
}
}
您可以使用新的PostController(postRepository)实例化该控制器。如果您需要一个用于后存储库的模拟,则可以使用一个名为Moq的库。 (使用nuget获取它)。只需写:
using Moq;
Mock<IPostRepository> postRepositoryMock = new Mock<IPostRepository>();
PostController controller = new PostController(postRepositoryMock.Object);
然后,您可以在Mock上使用Setup方法来返回所需的内容。例如,以某种方式返回给定类型int?的给定ID的测试Post来模拟Get方法:
postRepositoryMock.Setup(it => it.Get(It.IsAny<int?>()).Returns(new Post() { //here what you need to build your post object })
然后,您可以执行代码以从控制器获得结果,例如(测试代码是使用NUnit编写的,我不使用xunit,但是概念相同):
using Moq;
[TestFixture]
public class ExampleFixture()
{
[Test]
public void ExampleTest()
{
Mock<IPostRepository> postRepositoryMock = new Mock<IPostRepository>();
PostController controller = new PostController(postRepositoryMock.Object);
postRepositoryMock.Setup(it => it.Get(It.IsAny<int?>()).Returns(new Post() { //here what you need to build your post object })
var result = controller.GetPost(1);
Assert.That(result, Is.Not.Null, "Unexpected null result");
var retrievedPostContent = result as OkNegotiatedContentResult<Post>;
Assert.That(retrievedPostContent, Is.Not.Null, "Unexpected null retrievedPost");
var retrievedPost = result.Content;
Assert.That(retrievedPost.Id, Is.EqualTo(1), "retrievedPost.Id is unexpected")
}
}
使用xUnit应该成为:
using Xunit;
using Moq;
namespace ATestNamespace
{
public class TestFixture
{
public TestFixture()
{
}
[Fact]
public void Test()
{
Mock<IPostRepository> postRepositoryMock = new Mock<IPostRepository>();
PostController controller = new PostController(postRepositoryMock.Object);
postRepositoryMock.Setup(it => it.Get(It.IsAny<int?>()).Returns(new Post() { //here what you need to build your post object });
var result = controller.GetPost(1);
Assert.True(result != null,"Unexpected null result");
var retrievedPostResult = result as OkNegotiatedContentResult<Post>;
Assert.True(retrievedPostResult != null, "Unexpected null retrievedPost");
var retrievedPost = result.Content;
Assert.True(retrievedPost.Id == 1, "retrievedPost.Id is unexpected")
}
}
}