Как создать модульный тест для добавления элементов в репозиторий? - PullRequest
0 голосов
/ 17 октября 2018

У меня есть IUnitOfWork интерфейс, который инкапсулирует мои пользовательские репозитории.Мои пользовательские репозитории, в свою очередь, наследуют интерфейс IRepository .

// The class that I am attempting to unit test
// EmployeeBusiness.cs
private readonly IUnitOfWork _unitOfWork;

public EmployeeBusiness(IUnitOfWork unitOfWork)
{
    _unitOfWork = unitOfWork;
}


public EmployeeDto AddEmployee(EmployeeDto employeeDto)
{
    var employee = Mapper.Map<Employee>(employeeDto);

    if (employee == null) return null;

    _unitOfWork.Employees
        .Add(employee);

    _unitOfWork.Complete();

    return Mapper.Map<EmployeeDto>(employee); 
}

// IUnitOfWork interface
public interface IUnitOfWork : IDisposable
{
    IEmployeeRepository Employees { get; }

    void Complete();
}

// IEmployeeRepository interface
public interface IEmployeeRepository : IRepository<Employee> { }

// IRepository<T> interface
public interface IRepository<TEntity> where TEntity : class
{
    void Add(TEntity entity);

    // I have added other methods for simplicity
}

Я борюсь с модульным тестированием метода AddEmployee(), потому что я получаю эту ошибку:

Ожидаемый вызов для макета один раз, но был 0 раз: uow => uow.Employees.Add (Employee) Сконфигурированные настройки: IUnitOfWork uow => uow.Employees.Add (Employee) Выполненные вызовы: IRepository`1.Add (Сотрудник)

Это мой юнит тест

[SetUp]
public void SetUp()
{
    _employeeDto = new EmployeeDto
    {
        FirstName = "John",
        LastName = "Smith",
        BirthDate = new DateTime(1965, 12, 31)
    };

    _employee = new Employee
    {
       FirstName = "John",
       LastName = "Smith",
       BirthDate = new DateTime(1965, 12, 31)
    };

    _unitOfWork = new Mock<IUnitOfWork>();

    Mapper.Initialize(cfg =>
    {
        cfg.AddProfile<EmployeeProfile>();
    });
}


[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
    _unitOfWork.Setup(uow => uow.Employees.Add(_employee));
    _employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);

    _employeeBusiness.AddEmployee(_employeeDto);

    _unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once);
    _unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

Мне удалось заставить его работать, изменив мой модульный тест

[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
    _unitOfWork.Setup(uow => uow.Employees.Add(_employee));
    _employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);

    var result = _employeeBusiness.AddEmployee(_employeeDto);

    //_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once); <-- This did not work 

    _unitOfWork.Verify(uow => uow.Employees.Add(It.IsAny<Employee>()), Times.Once); // <-- After changing this to It.IsAny<Employee>() it worked 
    _unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}

Может кто-нибудь помочь мне понять разницу в использовании It.IsAny<Employee>() по сравнению с переменной _employee?


ОБНОВЛЕНИЕ

Объяснение можно найти на Ответ Торина .

0 голосов
/ 17 октября 2018

Причиной того, что тест, который вы предоставили в своем ответе (скопировано ниже), проходит, когда ваш оригинал терпит неудачу, состоит в том, что ваш оригинал ожидал вызова макета с конкретной ссылочной переменной, которую вы используете (в данном случае _employee).Возможно, вы ожидали, что Moq и .Verify () проверят на равенство, используя .equals () вместо ==?

В контексте тестируемого метода это правильно и желательно - на основе именитест, который вы просто ищете, чтобы проверить, что метод действительно отображает ваши входные данные в Employee и вызывает метод add репозитория.Если вы хотите убедиться, что данные не были потеряны в отображении, вы можете использовать It.Is (), который принимает функцию, которую вы можете использовать для подтверждения качества ввода (например, имени, соответствующего ожидаемому значению).

Если вы хотите просто проверить успешность сопоставления, вас может заинтересовать Проверка конфигурации Automapper как отдельный тест.

[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
    _unitOfWork.Setup(uow => uow.Employees.Add(_employee));
    _employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);

    var result = _employeeBusiness.AddEmployee(_employeeDto);

    //_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once); <-- This did not work 

    _unitOfWork.Verify(uow => uow.Employees.Add(It.IsAny<Employee>()), Times.Once); // <-- After changing this to It.IsAny<Employee>() it worked 
    _unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
0 голосов
/ 17 октября 2018

Вы не проверяете возвращаемое значение AddEmployee.

[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
    _unitOfWork.Setup(uow => uow.Employees.Add(_employee));
    _employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);

    var result = _employeeBusiness.AddEmployee(_employeeDto);

    Assert.IsNotNull(result); // <---

    _unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once);
    _unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
...