我正在使用 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
来模拟对象。我不确定这是否与故障测试有关。
如果有人能帮助我,我将非常感激。
单元测试构造函数不能包含使用
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);
}