我对编程非常陌生,只了解基础知识。
我目前正在为.net core 2.2控制器编写单元测试。我正在使用Rider,Nunit和Moq。
这里是我遇到问题的单元测试之一:
[Test]
[TestCase(true)]
[TestCase(false)]
public async Task GetPersonAsync_PersonDoesExist_ReturnOk(bool includeRelated)
{
_repository.Setup(r => r.GetPersonAsync(_id, includeRelated)).ReturnsAsync(_person);
_mapper.Setup(m => m.Map<Person, GetPersonResource>(It.IsAny<Person>())).Returns(_getPersonResource);
var result = await _controller.GetPersonAsync(_id);
Assert.That(result, Is.TypeOf<OkObjectResult>());
}
这是我的构造器/顶部和该单元测试的设置:
public class PersonsControllerTests
{
private Mock<IMapper> _mapper;
private Mock<IUnitOfWork> _unitOfWork;
private Mock<IClientsRepository> _repository;
private PersonsController _controller;
private int _id;
private Person _person;
private GetPersonResource _getPersonResource;
private CreatePersonResource _createPersonResource;
private UpdatePersonResource _updatePersonResource;
[SetUp]
public void Setup()
{
_mapper = new Mock<IMapper>();
_unitOfWork = new Mock<IUnitOfWork>();
_repository = new Mock<IClientsRepository>();
_controller = new PersonsController(_mapper.Object, _repository.Object, _unitOfWork.Object);
_id = 1;
_person = new Person {Id = 1};
_getPersonResource = new GetPersonResource {Id = 1};
_createPersonResource = new CreatePersonResource {Code = "a"};
_updatePersonResource = new UpdatePersonResource {Code = "a"};
}
这是我的控制器中的GetPersonAsync方法:
[HttpGet("{id}")]
public async Task<IActionResult> GetPersonAsync(int id)
{
var person = await repository.GetPersonAsync(id);
if (person == null)
return NotFound();
return Ok(mapper.Map<Person, GetPersonResource>(person));
}
这是我的控制器的构造器/顶部:
[Route("/api/persons")]
public class PersonsController : Controller
{
public IMapper mapper { get; }
private readonly IClientsRepository repository;
private readonly IUnitOfWork unitOfWork;
public PersonsController(IMapper mapper, IClientsRepository repository, IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
this.repository = repository;
this.mapper = mapper;
}
这是我的存储库中的GetPersonAsync方法:
public async Task<Person> GetPersonAsync(int id, bool includeRelated = true)
{
if (!includeRelated)
return await context.Persons
.FirstOrDefaultAsync(p => p.Id == id);
else
return await context.Persons
.Include(p => p.Clients)
.Include(p => p.ClientRelateds)
.ThenInclude(cr => cr.ClientRelationType)
.FirstOrDefaultAsync(p => p.Id == id);
}
这是我的IRepository中的GetPersonAsync签名:
Task<Person> GetPersonAsync(int id, bool includeRelated = true);
我遇到的问题是,每当我运行测试并将includeRelated参数更改为false时(默认情况下为true,我的测试都会失败。
例如,在我上面给出的测试用例为false的测试中,它应该返回Ok,但返回NotFound,当我使用真实的测试用例时,它返回Ok并通过,这正是我想要的。当我想查看是否保存模型时,我也得到相同的结果。我的将includeRelated设置为true的测试会调用_unitOfWork.CompleteAsync方法,但是当includeRelated设置为false时不会调用它。
当我在存储库中设置包括与false有关的include的默认值时,我所有包含includeRelated true的测试用例都会失败,而includeRelated false传递会失败。
[我很有可能在项目或单元测试中犯了一个错误,但是在我看来,如果我错了,请纠正我,当我在模拟存储库时,Moq会出现错误。存储库的实际实现(即,includeRelated的默认值为true)一点都不重要。
请注意,此处的存储库代码无关紧要,因为您在嘲笑它-该代码永远不会执行。相反,将为您设置的调用返回结果-所有其他调用都为返回类型返回.NET默认值-通常情况下为null
。
在您的设置中,已使存储库模拟条件为,当使用参数(1, true)
或(1, false)
调用时,返回值only,具体取决于正在运行的测试用例。每当仅使用参数(1)
调用它时,它将返回null。 IOW,您必须设置将实际使用的呼叫。您may希望设置所有三种可能性,以防灯具中的某些测试使用默认设置。
顺便说一句,使用默认参数测试方法非常棘手。
次要nitpick:您不需要[Test]
和IMO,在这种情况下它是丑陋且令人困惑的-乍一看就像是三个测试案例而不是两个测试案例。