Я хотел бы иметь возможность модульного тестирования этого кода
Какие конкретные проблемы мешают вам провести модульное тестирование этого класса?У него есть два метода, кажется довольно простым для написания модульного теста.
Имя - это CarFactory, но для меня это не похоже на Factory Pattern
Я считаю, Фабричный шаблон - это
Фабричный шаблон метода - это шаблон создания, который использует фабричные методы для решения проблемы создания объектов без указания точного класса объекта, которыйбудет создан
Я передаю имя автомобиля (поэтому я не указал тип), и он создает класс для меня.Вот и все.Это хороший пример одного?Не по моему мнению, но мое мнение о том, насколько хорошо это сделано, не меняет того, чем оно является.
Это не означает, что это не локатор службы, но это определенно фабричный метод. (Честно говоря, это не похоже на локатор служб, потому что он предоставляет только одну услугу)
модульное тестирование в таких средах, как Moq
Moqне является структурой юнит-тестирования.Moq - это Mocking Framework .Статические классы не легко Макет .Если вы можете использовать Mock, вы можете выполнить модульное тестирование с помощью методов, для которых требуется проверяемый класс.
статические классы .. чтобы они также скрывали зависимости.
Любой плохо разработанныйвсе может сделать что угодно.Статические классы по определению не предназначены для того, чтобы что-либо скрывать.
В этом случае я бы сказал, что этот статический класс не позволяет вам легко смоделировать его для модульного тестирования других методов, которые полагаются на статические классы.методы.
Я также хотел бы провести модульное тестирование этого класса и мне нужна помощь, чтобы сделать его модульным для тестирования с использованием Moq.
Опять же, ничто не мешает вамтестирование этого класса.
public class CarFactoryTests
{
public class MoqCar : CarBase { }
public void Register_WithValidParameters_DoesNotThrowException
{
// Act
Assert.DoesNotThrow(() => CarFactory.Register<MoqCar>(
nameof(Register_WithValidParameters_DoesNotThrowException)));
}
public void Create_WithValidCar_DoesNotThrowException
{
CarFactory.Register<MoqCar>(
nameof(Create_WithValidParameters_DoesNotThrowException));
Assert.DoesNotThrow(() => CarFactory.Create(
nameof(Create_WithValidParameters_DoesNotThrowException));
}
// etc etc
}
Проблема, с которой вы можете столкнуться:
public class CarConsumer
{
public void ICar GetRedCar()
{
var result = CarFactory.Create("Tesla");
result.Color = Color.Red;
return result;
}
}
Тестирование этого метода означает, что вы не полностью контролируете метод, поскольку существует внешний код GetRedCar()
опирается на.Вы не можете написать чистый модульный тест здесь.
Вот почему вам нужно преобразовать CarFactory в экземплярный класс .И затем убедитесь, что он имеет правильное время жизни для любой используемой вами структуры DI.
public class CarConsumer
{
private ICarFactory _carFactory;
public CarConsumer(ICarFactory carFactory)
{
_carFactory = carFactory;
}
public void ICar GetRedCar()
{
var result = _carFactory.Create("Tesla");
result.Color = Color.Red;
return result;
}
}
Теперь мы можем Moq ICarfactory
и написать чистый модульный тест по GetRedCar()
.
Следующее не рекомендуется.
Если по какой-либо причине вы застряли с этим типом Фабрики, но все еще хотите писать чистые модульные тесты, вы можете сделать что-то вроде:
public class CarConsumer
{
private Func<string, ICar> _createCar;
public CarConsumer(Func<string, ICar> createCar= CarFactory.Create)
{
_createCar = createCar;
}
public void ICar GetRedCar()
{
var result = _createCar("Tesla");
result.Color = Color.Red;
return result;
}
}
Мы можем Moq этого типа Func, но на самом деле это простокостыль для реальной проблемы.
Наверное, реальный вопрос, который у меня возникает, состоит в том, как сделать мой CarFactory таким образом, чтобы методы из других классов, использующих его, можно было протестировать с помощью Moq?
public interface ICarFactory
{
void Register<TCar>(string car) where TCar : CarBase, new();
ICar Create(string car);
}
public class CarFactory : ICarFactory
{
private readonly IDictionary<string, Type> CarsRegistry
= new Dictionary<string, Type>();
public void Register<TCar>(string car) where TCar : CarBase, new()
{
if (!CarsRegistry.ContainsKey(car))
{
CarsRegistry.Add(car, typeof(TCar));
}
}
public ICar Create(string car)
{
if (CarsRegistry.ContainsKey(car))
{
CarBase newCar = (CarBase)Activator.CreateInstance(CarsRegistry[car]);
return newCar;
}
throw new NotSupportedException($"Unknown '{car}'");
}
}