Насмешка из репозитория возвращает NULL - PullRequest
0 голосов
/ 14 февраля 2019

Я новичок в издевательстве и не уверен, правильно ли я делаю.Я пытаюсь использовать функцию WriteNameToDatabase, которая использует метод GetName, поэтому мои настройки классов выглядят так:

Мой интерфейс сотрудника:

public interface IEmployee
{
    Task<string> GetName();
   string WriteNameToDataBase();

}

Мой класс сотрудника

 public class Employee : IEmployee
    {
        public Task<string> GetName()
        {
            throw new NotImplementedException();
        }

        public string WriteNameToDataBase()
        {
            var employeeName = GetName();

            return $"Wrote {employeeName.Result} to database";

        }

Класс моего модульного теста

 [Test]

    public void WriteToDBShouldWrite()
    {
        var mockObject = new Mock<IEmployee>();
        mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");

        string result = mockObject.Object.WriteNameToDataBase();

        Assert.AreEqual("Wrote Frank to database", result);

    }

Это всегда возвращает меня Was Expecting 'Wrote Frank to database, но на самом деле оно было нулевым или что-то в этом роде, что дает мне Assert.Что я делаю не так?

Спасибо

Редактировать: Исправлено для использования ReturnsAsync("Frank");

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Обратите внимание, что вы создаете объект Mock на основе интерфейса IEmployee, а не класса Employee, поэтому вы вообще не тестируете свой класс Employee, поэтому вы не можете ожидать никакого кода в Employee класс для запуска.

Вам нужно подумать о том, что на самом деле пытается сделать ваш тест, и что представляет собой «единица» в вашем проекте.

Вы можете создать новый интерфейс INameGetter (или что-то с именем, которое имеет смысл для вашего проекта), которое содержит метод GetName.Затем вы можете взять этот новый интерфейс как зависимость в своем классе сотрудников и смоделировать его в своем тесте.Что-то вроде:

public interface IEmployee
{
   Task<string> WriteNameToDataBase();
}

public interface INameGetter
{
   Task<string> GetName();
}

public class Employee : IEmployee
{
     private INameGetter nameGetter;

     public Employee(INameGetter n)
     {
         nameGetter = n;
     }

    public Task<string> WriteNameToDataBase()
    {
        var employeeName = await nameGetter.GetName();

        return $"Wrote {employeeName} to database";
    }
}

И ваш метод тестирования

[Test]
public void WriteToDBShouldWrite()
{
    var mockObject = new Mock<INameGetter>();
    mockObject.Setup(x =>  x.GetName()).Returns(Task.FromResult("Frank"));

    string result =  new Employee(mockObject.Object).WriteNameToDataBase();

    Assert.AreEqual("Wrote Frank to database", result);

}

NB Вам также нужно изучить async / await для использования методов, возвращающих Task.Редактировать: я сейчас исправил это здесь, но по сути вы не хотите использовать Task.Result.

0 голосов
/ 14 февраля 2019

Несколько проблем, одна из которых вы не ожидаете асинхронного вызова:

    public async Task<string> WriteNameToDataBase()
    {
        var employeeName = await GetName();

        return $"Wrote {employeeName} to database";

    }

две ваши насмешки неверного результата, moq поддерживает async:

mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");

Но большая проблемаздесь вы издеваетесь над всем объектом.Это ничего не проверяет.Вы, вероятно, хотите что-то более похожее на:

public class Employee : IEmployee
{
    private readonly INameRepo _repo;
    public Employee(INameRepo repo)
    {
         //this is dependancy injection
         _repo = repo;
    }

    public async Task<string> WriteNameToDataBase()
    {
        var employeeName = await _repo.GetName();

        return $"Wrote {employeeName.Result} to database";

    }
 }

Ваше хранилище теперь представляет собой отдельную вещь, представленную этим интерфейсом

public interface INameRepo
{
      Task<string> GetName();
}

Тогда ваш тест будет выглядеть так:

[Test]
//note this is also async now
public async Task WriteToDBShouldWrite()
{
    //mock the dependencies
    var mockObject = new Mock<INameRepo>();
    mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");

    //test the actual object
    Employee emp = new Employee(mockObject.Object);
    string result = await emp.WriteToDBShouldWrite();

    Assert.AreEqual("Wrote Frank to database", result);

}

Если вы просто хотите убедиться, что вызывается GetName, вы должны использовать Verify вместо возврата произвольного значения:

[Test]
//note this is also async now
public async Task WriteToDBShouldWrite()
{
    var mockObject = new Mock<INameRepo>();
    mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");

    string result = mockObject.Object.WriteNameToDataBase();

    Employee emp = new Employee(mockObject.Object);
    await emp.WriteToDBShouldWrite();

    //ensure GetName is called once and once only
    mockObject.Verify(v => v.GetName(), TimesOnce);

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