Как я могу протестировать конкретный метод в моем классе обслуживания, используя макет C #?

#c# #unit-testing

#c# #модульное тестирование

Вопрос:

Пожалуйста, помогите мне с моей проблемой. У меня есть класс обслуживания, который приведен ниже:

 public class RateService:IRatesService
{
    ...
    public RatesDTO GetById(int Id)
    {
        return Mapper.Map<Rates, RatesDTO>(this.db.Rates.GetAll().Where(m => m.RateId == Id).First());
    }
}
  

Интерфейс IRatesServicelooks похож на этот пример кода:

 public interface IRatesService
{
    .....
    RatesDTO GetById(int Id);
    ....
}
  

И теперь я пытаюсь протестировать общедоступный метод RatesDTO GetById(int Id). Мой код приведен ниже:

 [TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Mock<IRatesService> mock = new Mock<IRatesService>();
        mock.Setup(m => m.GetById(It.IsAny<int>())).Returns<RatesDTO>(total=>total);

        Assert.IsNotNull(mock.Object.GetById(1));
    }
}
  

Но когда я запускаю test, я получаю такую ошибку:

Имя теста:
TestMethod 1 Полное имя теста: Provider.Тесты.Услуги.UnitTest1.TestMethod 1

Сообщение о результате:

Поставщик методов тестирования.Тесты.Услуги.UnitTest1.TestMethod 1 выдал исключение: System.ArgumentException: Невозможно преобразовать объект типа «System.Int32» к типу «Provider.BLL.DTO.RatesDTO».

Как лучше всего протестировать классы и методы обслуживания?

Комментарии:

1. Если вы пытаетесь протестировать RateService, вам следует протестировать конкретный класс, и вы не должны издеваться над ним. Mocks существует для случаев, когда вы хотите протестировать класс изолированно, поэтому вы имитируете объекты, от которых зависит класс.

Ответ №1:

Вы пытаетесь протестировать свой макет. Это не имеет никакого смысла.

Вы должны стремиться протестировать свой реальный код.В вашем случае вы можете убедиться, что ваш GetById возвращает RatesDTO с правильным значением id.

Вы могли бы использовать макет фреймворка для облегчения тестирования. например, если вы пытаетесь выполнить модульный тест и используете уровень БД, вы можете создать макет функции GetAll уровня базы данных и вернуть несколько объектов, а затем запустить тест, чтобы проверить, что вы действительно возвращаете правильный объект (тот же идентификатор).

Ответ №2:

Ваша RateService система находится в стадии тестирования. При создании макетов для ваших модульных тестов нормой является имитация зависимостей тестируемой системы.

Итак, учитывая ваш текущий сервис, допустим, он зависит от хранилища данных.

 public class RateService : IRatesService {
    private readonly IDbContext db;
    public RateService(IDbContext dbContext) {
        this.db = dbContext;
    }
    //...
    public RatesDTO GetById(int Id) {
        return Mapper.Map<Rates, RatesDTO>(this.db.Rates.GetAll().Where(m => m.RateId == Id).First());
    }
    //...
}
  

IDbContext будет ли зависимость от тестируемой системы.

Вы бы смоделировали это при тестировании RateService

 [TestClass]
public class RateServiceUnitTests {
    [TestMethod]
    public void Given_ValidId_GetById_Should_Return_Dto() {
        //Arrange
        var validId = 1;
        var fakes = new List<Rates>() {
            new Rates { RateId = validId }
        };
        var mock = new Mock<IDbContext>();
        //Assuming IDbContext.Rates.GetAll() returns an IEnumerable<Rates>
        mock.Setup(m => m.Rates.GetAll()).Returns(fakes);
        var sut = new RateService(mock.Object);
        //Act
        var result = sut.GetById(validId);
        //Assert
        Assert.IsNotNull(result);
    }
}
  

Заметил, что вы также используете mapper. Вы должны убедиться, что он также настроен для теста, иначе тест завершится неудачей. При использовании статических вызовов в ваших классах они могут вызвать проблемы при попытке изолировать вашу систему для тестирования. Попробуйте также добавить mapper в качестве зависимости.