首页 > 解决方案 > 获取 InMemoryDb 数据时,测试环境中的 DataService 始终返回 null

问题描述

public class TestStartup : Startup
{
    private readonly Mock<ICarService> _carServiceMock;
    public TestStartup(IConfiguration configuration) : base(configuration)
    {
        _carServiceMock = new Mock<ICarService>();
    }

    public override void ConfigureMyServices(IServiceCollection services)
    {
        services.AddSingleton(_carServiceMock.Object);
    }

    public override void ConfigureDatabase(IServiceCollection services)
    {
        services.AddDbContext<CarContext>(options => options.UseInMemoryDatabase("CarDb"));
        services.AddTransient<DataSeed>();
    }   
}

public class TestFixture: IDisposable, ICollectionFixture<TestFixture>
{
    public TestFixture()
    {
         _server = new TestServer(new WebHostBuilder()
            .UseStartup<TestStartup>()
            .UseEnvironment("Development"));
          _client = _server.CreateClient();
    }
}

我正在使用的内部控制器ICarService用于CarContext从数据库中检索数据。

public class CarController
{
    private readonly ICarService _carService;

    public CarController(ICarService carService)
    {
        _carService = carService;            
    }

    [HttpGet]
    public async Task<IActionResult> Get([FromRoute] int id)
    {
        var contact = await _carService.GetAsync(id); **// this is always null**
    }
}

我的问题是:由于这是一个集成测试,我是否需要首先模拟 ICarService ,如果是,我在这里做错了什么?

标签: c#.nettesting.net-core

解决方案


如果您正在测试CarService该类如何与数据库交互,那么您不应该模拟它。

您要做的是使用真正的实现,并让依赖注入将 InMemoryDatabase 作为参数CarService添加到该类中。CarContext

因此,请删除Mock<ICarService>并注册真实的。

为什么它返回null?

在您的示例中,当您调用该方法时_carService.GetAsync(id),它正在调用模拟类。但是你在模拟上没有Setup任何方法,所以任何调用都会返回null

您需要添加以下内容以使模拟方法返回一个值:

_carService.Setup(cs => cs.GetAsync(It.IsAny<int>()).Returns(1);

但这不会调用内存数据库,因为您正在使用模拟 for CarService.


推荐阅读