XUnit 服务层测试核心 3 System.ArgumentNullException

XUnit Service Layer Testing Core 3 System.ArgumentNullException

虽然我有使用另一种语言的 TDD 经验,但我很难理解 .NET Core 3 中的测试。我正在使用 Entity Framework,并尝试在我的服务层上生成测试。我已经看到了一些存储库示例和一些基于 API 的示例,但我还没有弄清楚我做错了什么。

我在 运行 测试时遇到 System.ArgumentNullException : Value cannot be null. (Parameter 'source') 错误。

ICustomerService.cs

public interface ICustomerService
{
    List<Customer> GetCustomers();
}

CustomerService.cs

public class CustomerService : ICustomerService
{
    private readonly DbContext _db;
    public CustomerService(DbContext db)
    {
        _db = db;
    }

    public List<Customer> GetCustomers()
    {
        return _db.Customer.ToList();
    }
}

CustomerServiceTests.cs

[Fact]
public void GetCustomersReturnsRecords()
  {
    // Arrange
    var cntxt = new Mock<DbContext>();
    CustomerService cs = new CustomerService(cntxt.Object);

    // Act
    var result = cs.GetCustomers();

    //Asserts here
    Assert.NotNull(result);
  }

与其尝试模拟 DbContext,不如考虑使用内存数据库。

Unit testing

Consider testing a piece of business logic that might need to use some data from a database, but is not inherently testing the database interactions. One option is to use a test double such as a mock or fake.

We use test doubles for internal testing of EF Core. However, we never try to mock DbContext or IQueryable. Doing so is difficult, cumbersome, and fragile. Don't do it.

Instead we use the EF in-memory database when unit testing something that uses DbContext. In this case using the EF in-memory database is appropriate because the test is not dependent on database behavior. Just don't do this to test actual database queries or updates.

引用Testing code that uses EF Core

这是文档中建议的方法。

[Fact]
public void GetCustomersReturnsRecords() {
    // Arrange
    var builder = new DbContextOptionsBuilder<MyDbContext>();
    builder.UseInMemoryDatabase();
    var options = builder.Options;
    using(var context = new MyDbContext(options)) {
        CustomerService subject = new CustomerService(context);

        // Act
        var result = subject.GetCustomers();

        //Asserts here
        Assert.NotNull(result);
    }
}

引用Testing with the EF In-Memory Database