如何修复 Xunit 中的“以下构造函数参数没有匹配的夹具数据:存储库存储库、IMapper 映射器、ILogger 记录器”?

问题描述 投票:0回答:1

我正在使用 Xunit 为测试驱动开发应用程序编写一些测试。但由于某种原因,在我初始化构造函数的那一刻,服务器抛出了异常

以下构造函数参数没有匹配的装置数据:Repository repo、IMapper 映射器、ILogger 记录器

这是存储库:

public class Repository 
{
    private IList<Subject> _subjects = new List<Subject>()
    {
        new Subject() 
            { 
                SubjectId = Guid.Parse("de331c36-6b31-4dd9-b50d-f677e51b987c"), 
                Title = "Math", 
                Credits = 8
            };       
    };

    public IEnumerable<Subject> GetAll() => _subjects;

    public Subject? GetById(Guid id) =>   
         _subjects.FirstOrDefault(x => x.SubjectId == id);

    public void Create(Subject subject) 
    {
        _subjects.Add(subject);
    }
}

这是控制器:

public class Controllers : ControllerBase
{
    private Repository _repo;
    private ILogger _logger;
    private IMapper _mapper;

    public Controllers(Repository repo, ILogger logger, IMapper mapper)
    {
        _repo = repo;
        _logger = logger; 
        _mapper = mapper;
    }

    public IActionResult CreateSubject(SubjectCreateDto subject)
    {
        if (subject == null)
        {
            _logger.LogError("Subject sent is null");
        }

        var subjectEntity = _mapper.Map<Subject>(subject);
        _repo.Create(subjectEntity);
       
       return Ok(subjectEntity);
    }
}

这些是测试:

public class UnitTest1: IClassFixture<Controllers>
{
    private Repository _repo;
    private IMapper _mapper;
    private ILogger _logger;

    public UnitTest1(Repository repo, IMapper mapper, ILogger logger) 
    {
        _repo = repo;
        _logger = logger;
        _mapper = mapper;
    }

    [Fact]
    public void CreateSubjectTest()
    {
        // Arrange
        var _subject = new Controllers(_repo, _logger, _mapper);
        var subject = new Subject()
        {
            SubjectId = Guid.Parse("22de7cb0-0453-4435-a219-3157bf3e3302"), 
            Title = "History", 
            Credits = 10,
        };

        // Act
        var subjectCreate = _mapper.Map<SubjectCreateDto>(subject);     
        var result = _subject.CreateSubject(subjectCreate) as ObjectResult;       
        
        // Assert
        Assert.NotNull(result);
        Assert.IsAssignableFrom<CreatedAtRouteResult>(result);
        Assert.Equal((int)HttpStatusCode.Created, result!.StatusCode);
    } 
}

我必须承认我避免对存储库使用模拟。接下来,我决定使用简单的

IList
来模拟对象。我不确定这是否与故障测试有关。

如果有人能帮助我,我将非常感激。

c# asp.net unit-testing xunit
1个回答
0
投票

单元测试构造函数不能包含使用

IClassFixture
注入的参数之外的参数。我认为您误解了
IClassFixture
课程的目的。
IClassFixture
负责创建一个在其构造函数中不需要参数的类的实例,然后将该实例注入到类构造函数中。我将提供一个示例来帮助您了解使用
IClassFixture
时代码的外观。但是,我建议在这种情况下不要使用
IClassFixture
;相反,我会在单元测试构造函数中创建控制器实例。

UnitTest1.cs

public class UnitTest1 : IClassFixture<ControllersFixture>
{
    private Controllers _controllers;

    public UnitTest1(ControllersFixture fixture)
    {
        _controllers = fixture.Controllers;
    }

    [Fact]
    public void CreateSubjectTest()
    {
        // Arrange
        var subject = new Subject()
        {
            SubjectId = Guid.Parse("22de7cb0-0453-4435-a219-3157bf3e3302"),
            Title = "History",
            Credits = 10,
        };

        // Act
        var subjectCreate = _controllers.Mapper.Map<SubjectCreateDto>(subject);
        var result = _controllers.CreateSubject(subjectCreate) as ObjectResult;

        // Assert
        Assert.NotNull(result);
        Assert.IsAssignableFrom<CreatedAtRouteResult>(result);
        Assert.Equal((int)HttpStatusCode.Created, result!.StatusCode);
    }
}

控制器Fixture.cs

public class ControllersFixture
{
    public Controllers Controllers { get; private set; }

    public ControllersFixture()
    {
        // You need to initialize your dependencies (repo, logger, mapper) here.
        var repo = new Repository(); // Initialize your repo with necessary data
        var logger = new YourLoggerImplementation(); // Initialize your logger
        var mapper = new YourMapperImplementation(); // Initialize your mapper

        Controllers = new Controllers(repo, logger, mapper);
    }
}

我建议您在这种情况下这样做(删除

IClassFixture
,您不需要它):

UnitTest1.cs

public class UnitTest1
{
    private Controllers _controllers;

    public UnitTest1()
    {
        // You need to initialize your dependencies (repo, logger, mapper) here.
        var repo = new Repository(); // Initialize your repo with necessary data
        var logger = new YourLoggerImplementation(); // Initialize your logger
        var mapper = new YourMapperImplementation(); // Initialize your mapper

        _controllers= new Controllers(repo, logger, mapper);
    }

    [Fact]
    public void CreateSubjectTest()
    {
        // Arrange
        var subject = new Subject()
        {
            SubjectId = Guid.Parse("22de7cb0-0453-4435-a219-3157bf3e3302"),
            Title = "History",
            Credits = 10,
        };

        // Act
        var subjectCreate = _controllers.Mapper.Map<SubjectCreateDto>(subject);
        var result = _controllers.CreateSubject(subjectCreate) as ObjectResult;

        // Assert
        Assert.NotNull(result);
        Assert.IsAssignableFrom<CreatedAtRouteResult>(result);
        Assert.Equal((int)HttpStatusCode.Created, result!.StatusCode);
    }
}

要在此控制器上初始化所需的服务,您可以执行以下操作:

    public UnitTest1()
    {
        var repo = new Repository();
        var logger = new Mock<ILogger<Controllers>>();
        ServiceProvider serviceProvider = new ServiceCollection().AddAutoMapper(typeof(Program)).BuildServiceProvider();
        mapper = serviceProvider.GetRequiredService<IMapper>(); // Initialize your mapper with the proyect configuration, the typeof(Program) is the initial class of your proyect
    
        _controllers= new Controllers(repo, logger, mapper);
    }
© www.soinside.com 2019 - 2024. All rights reserved.