.net 具有依赖注入的DbContext

rn0zuynd  于 2023-03-20  发布在  .NET
关注(0)|答案(1)|浏览(177)

我知道这个问题有点像很多问题的重复,但我一辈子都搞不清楚我是不是在犯傻,错过了一些非常明显的东西。我现在需要比我更聪明的人给我指路(或者告诉我我没有疯)。
基本上,我在一次面试中遇到了一个编码挑战(我不是想作弊,请原谅我)。现在提供的代码“工作”了,就像它构建和运行一样,除了它实际上并不工作。这里只是提供的控制器之一的一个片段(为更通用的东西更改名称)。

public class ExampleController : BaseApiController
{
    private readonly SomeRepository _repository;

    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult> GetAll()
    {
        var items = await _repository.Items.GetAllAsync();
        return Ok(items);
    }

这是BaseApiController的外观:

[Route("api/[controller]")]
    public class BaseApiController : ControllerBase
    { }

现在问题很明显了,_repository从来没有初始化过。所以我添加了一个构造函数来初始化它,并添加了DbContext(SomeRepository依赖于它):

public class ExampleController : BaseApiController
{
    private readonly SomeRepository _repository;

    public class ExampleController(SomeDbContext context){
        _repository = new SomeRepository(context);
    }

    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult> GetAll()
    {
        var items = await _repository.Items.GetAllAsync();
        return Ok(items);
    }

这是可行的,我通过postman测试了它,并且能够取回数据。然而,它破坏了挑战中提供的每一个单元测试。为什么?提供的测试使用基构造函数初始化ExampleController类。下面是一个示例:

public class ExampleControllerTests
{
    private readonly Mock<ISomeRepository> _repository;

    public ExampleControllerTests()
    {
        this._repository = new Mock<ISomeRepository>();
    }

[Fact]
    public async Task Get_OnSuccess_ReturnsListOfItems()
    {
        Item[] monsters = ItemFixture.GetItemsMock().ToArray();

        this._repository
            .Setup(x => x.Items.GetAllAsync())
            .ReturnsAsync(items);

        ExampleController sut = new ExampleController();

        ActionResult result = await sut.GetAll();
        OkObjectResult objectResults = (OkObjectResult) result;
        objectResults?.Value.Should().BeOfType<Item[]>();
    }

显然,我不应该修改他们提供的测试,那么有没有一种方法可以在ExampleController中获取DbContext,而无需创建一个将其作为参数的构造函数?或者,我应该自己解决测试问题(在这种情况下,如何解决?尝试初始化DbContext不起作用,因为它需要DbContextOptions)。

x4shl7ld

x4shl7ld1#

看起来他们已经注册了所有需要注入控制器的依赖项,否则注入DbContext将会失败。
你提供的测试肯定是不完整的,应该被修复。他们在模仿ISomeRepository,但没有以任何方式使用它。更不用说ExampleController sut = new ExampleController();不会起作用,因为你添加了DbContext作为构造函数参数。
我假设ISomeRepository被绑定在DI容器的某个地方(和DbContext一起),那么ExampleController看起来就像这样:

public class ExampleController : BaseApiController
{
    private readonly ISomeRepository _repository;

    public class ExampleController(ISomeRepository repository){
        _repository = repository;
    }

    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult> GetAll()
    {
        var items = await _repository.Items.GetAllAsync();
        return Ok(items);
    }
}

然后,测试将使用模拟接口来验证GetAll方法。

public class ExampleControllerTests
{
    private readonly Mock<ISomeRepository> _repository;

    public ExampleControllerTests()
    {
        this._repository = new Mock<ISomeRepository>();
    }

    public async Task Get_OnSuccess_ReturnsListOfItems()
    {
        Item[] monsters = ItemFixture.GetItemsMock().ToArray();

        this._repository
            .Setup(x => x.Items.GetAllAsync())
            .ReturnsAsync(items);

        ExampleController sut = new ExampleController(_repository.Object);

        ActionResult result = await sut.GetAll();
        OkObjectResult objectResults = (OkObjectResult) result;
        objectResults?.Value.Should().BeOfType<Item[]>();
    }
}

相关问题