使用 xUnit web api 对 Get() 方法进行单元测试

Unit test the Get() Method using xUnit web api

有谁知道如何为以下 Get() 方法编写单元测试(使用 xUnit)? Get() 方法在控制器和所有类别的 returns 列表中:

public class CategoryController : Controller
{
    private MyContext x;

    public CategoryController(MyContext y)
    {
        x = y;
    }

    [HttpGet]
    public ActionResult<IEnumerable<Category>> Get()
    {
        return x.Categories.ToList();
    }
}

如果您使用 EF Core 作为 ORM,您可以使用 In Memory 数据库进行单元测试。 有简单的例子:

[Fact]
public void TestGet()
{
    _options = new DbContextOptionsBuilder<MyContext>()
        .UseInMemoryDatabase(databaseName: "default")
        .Options;
    var context = new MyContext(_options);
    context.EnsureSeed();
    var controller = new CategoryController(context);

    //Act
    var results = controller.Get();

    //Assert
    Assert.NotNull(results);
    Assert.True(results.Count > 0, "Expected to be greater than 0.");
}

您还需要实施 EnsureSeed 方法。示例:

public static void EnsureSeed(this MyContext dataContext)
{
     //Check if database is created, if not - create
     dataContext.Database.EnsureCreated();

     var category = new Category()
     {
          Id = 1
     };
     dataContext.Categories.Add(category);    
     dataContext.SaveChanges();
}

据我所知,对控制器功能进行单元测试的最佳方法是从您的测试设置创建服务器主机实例,并直接向您的端点发出请求 - 这将允许您测试传输应用程序的层,例如 API 合同和 Http 协议。 下面是在.Net Core中实现的例子:

    [Trait]
    public class CategoryControllerTests : IClassFixture<WebApplicationFactory<Startup>>
    {
        // Startup - the entry point of most .net core project
        private readonly WebApplicationFactory<Startup> _factory;

        public CategoryControllerTests(WebApplicationFactory<Startup> factory)
        {
            // Any webhost config needed to run tests against the test
            _factory = factory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(services =>
                {
                    // register any mock dependancies there - any dependencies in Startup.cs will hold unless overridden by a mock
                    services.AddScoped(x => new Mock() );
                });
            });

        }

        [Fact]
        public async Task Get_ValidRequest_ReturnsData()
        {
            var client = _factory.CreateClient();
            // Whatever routing protocol you use to define your endpoints
            var url = "/category";
            var response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();
            var content = await response.Content.ReadAsAsync<List<Category>>();
            
            // Any asserts on your response
            Assert.NotNull(content);
        }
     }

这取决于您设置项目 startup/initialisation 的方式,它将允许您像在生产环境中 运行 一样测试项目,同时允许您模拟任何真正单元测试的传输层下的依赖关系。

注意:使用 IClassFixture - 这将使您可以重用 WebApplicationFactory 的实例以加快测试执行速度; XUnit 将把它作为框架的一部分为您注入。