Проблема с модульным тестом, когда параметр-тестировщик изменяет аргумент со значением по умолчанию - PullRequest
0 голосов
/ 16 октября 2019

Я довольно новичок в программировании и знаю только основы.

В настоящее время я пишу юнит-тест для контроллера .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);
    }

Вот моя подпись GetPersonAsync в моем IRepository:

Task<Person> GetPersonAsync(int id, bool includeRelated = true);

Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я запускаю тест иизмените аргумент includeRelated на false, что по умолчанию равно true, мои тесты не пройдены.

Например, в тесте, который я дал выше, мой тест с тестом case false, должен возвращать Ok, но возвращает NotFound,когда я использую настоящий тестовый пример, он возвращает Ok и проходит, что я и хочу. Я также получаю то же самое, когда хочу посмотреть, сохранена ли модель. Мой тест, где includeRelated установлен в true, вызывает мой метод _unitOfWork.CompleteAsync, но не вызывает его, когда для includeRelated установлено значение false.

Когда я устанавливаю значение по умолчанию include, связанное с false, в моем репозитории во всех моих тестовых случаяхс includeRelated true с ошибками и includeRelated false pass.

Существует большая вероятность, что я либо допустил ошибку в своем проекте или в моем модульном тесте, но мне кажется, что это так, и исправьте меня, если я ошибаюсь,В Moq есть ошибка, так как я проверяю хранилище, и фактическая реализация хранилища (т. е. значение по умолчанию true для includeRelated) вообще не имеет значения.

1 Ответ

0 голосов
/ 16 октября 2019

Просто чтобы прояснить, код для вашего хранилища здесь не имеет значения, потому что вы его высмеиваете - этот код никогда не выполняется. Вместо этого результаты возвращаются для вызовов, которые вы настроили - все остальные вызовы возвращают .NET по умолчанию для типа возврата - как правило, null в вашем случае.

В вашей настройке вы установили макет хранилищавозвращать значение только при вызове с аргументами (1, true) или (1, false), в зависимости от того, какой тестовый пример выполняется. Каждый раз, когда SUT вызывает его только с аргументом (1), будет использоваться true, даже если вы намерены проверить случай false. Человек будет возвращен как ноль. IOW, вы должны настроить вызовы, которые будут фактически использоваться контроллером. Для надежного теста вы должны установить разные возвращаемые значения для обеих возможностей.

Тестирование методов с аргументами по умолчанию, как известно, сложно. Вы должны учитывать возможность того, что SUT не всегда будет использовать аргумент, который вы ожидаете, но на самом деле может использовать значение по умолчанию.

Незначительный придир: вам не нужны [Test] и IMO, это уродливои сбивает с толку в этом контексте - на первый взгляд все выглядит так, как будто есть три теста, а не два.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...