Я работаю над приложением, которое имеет несколько слоев. Уровень доступа к данным для извлечения и сохранения данных из источника данных, бизнес-логика для управления данными, пользовательский интерфейс для отображения данных на экране.
Я также занимаюсь модульным тестированием уровня бизнес-логики. Единственное требование - проверить поток логики бизнес-уровня. Поэтому я использую инфраструктуру Moq для моделирования уровня доступа к данным и модульного тестирования уровня бизнес-логики с MS Unit.
Я использую программирование интерфейса, чтобы максимально отделить дизайн, чтобы можно было выполнить модульное тестирование. Бизнес-уровень вызова уровня доступа к данным через интерфейс.
Я сталкиваюсь с проблемой, когда пытаюсь проверить один из методов бизнес-логики. Этот метод выполняет некоторую работу, создает объект и передает его на уровень доступа к данным. Когда я пытаюсь смоделировать этот метод уровня доступа к данным, он не может успешно смоделировать.
Здесь я пытаюсь создать демонстрационный код, чтобы показать мою проблему.
Модель:
public class Employee
{
public string Name { get; set; }
}
Уровень доступа к данным:
public interface IDal
{
string GetMessage(Employee emp);
}
public class Dal : IDal
{
public string GetMessage(Employee emp)
{
// Doing some data source access work...
return string.Format("Hello {0}", emp.Name);
}
}
Уровень бизнес-логики:
public interface IBll
{
string GetMessage();
}
public class Bll : IBll
{
private readonly IDal _dal;
public Bll(IDal dal)
{
_dal = dal;
}
public string GetMessage()
{
// Object creating inside business logic method.
Employee emp = new Employee();
string msg = _dal.GetMessage(emp);
return msg;
}
}
Модульный тест:
[TestMethod]
public void Is_GetMessage_Return_Proper_Result()
{
// Arrange.
Employee emp = new Employee; // New object.
Mock<IDal> mockDal = new Mock<IDal>();
mockDal.Setup(d => d.GetMessage(emp)).Returns("Hello " + emp.Name);
IBll bll = new Bll(mockDal.Object);
// Act.
// This will create another employee object inside the
// business logic method, which is different from the
// object which I have sent at the time of mocking.
string msg = bll.GetMessage();
// Assert.
Assert.AreEqual("Hello arnab", msg);
}
В случае модульного теста во время моделирования я отправляю объект Employee, но при вызове метода бизнес-логики он создает другой объект Employee внутри метода. Вот почему я не могу издеваться над объектом.
В таком случае, как спроектировать, чтобы я мог решить проблему?
источник
Ответы:
Вместо того чтобы создавать
Employee
объект напрямую с помощьюnew
, ваш классBll
может использоватьEmployeeFactory
для этого класс с методомcreateInstance
, который вводится через конструктор:Конструктор должен передавать фабричный объект через интерфейс
IEmployeeFactory
, чтобы вы могли легко заменить «настоящую» фабрику фиктивной фабрикой.Поддельная фабрика может предоставить тесту любой
Employee
объект, который вам нужен для теста (например,createInstance
всегда может вернуть один и тот же объект):Теперь использование этого макета в вашем тесте должно помочь.
источник
Я бы отнесся к нему как к единому устройству для тестирования.
Пока вы контролируете все входные данные, из которых
Employee
создается объект, сам факт его создания в тестируемом объекте не должен иметь значения. Вам просто нужен метод mock, чтобы вернуть ожидаемый результат, если содержимое аргумента соответствует ожидаемому.Очевидно, это означает, что вам нужно предоставить собственную логику для метода макета. Продвинутая логика часто не может быть проверена только с помощью форм «for x return y».
На самом деле, вы не должны заставлять его возвращать другой объект в тестах, чем в производственном процессе, потому что если бы вы это сделали, вы бы не тестировали код, который должен его создать. Но этот код является неотъемлемой частью производственного кода и поэтому должен также охватываться тестовым примером.
источник
Employee
объект в тестах, вы не будете тестировать код, который его обычно создает. Так что не стоит это менять.Это сбой некоторых инструментов тестирования, вы всегда должны использовать интерфейсы, и все должно быть создано таким образом, чтобы вы могли поменять объект на основе интерфейса на другой.
Однако есть и лучшие инструменты - Microsoft Fakes (называлась Moles), которая позволяет заменять любые объекты, даже статические и глобальные. Для замены объектов требуется более низкоуровневый подход, поэтому вам не нужно везде использовать интерфейсы, сохраняя при этом способ написания тестов, к которым вы привыкли.
источник