Идея модульных тестов состоит в том, чтобы тестировать определенную функциональность класса без его зависимостей (например, базы данных, файловой системы или сети).
Для этого вам необходимо спроектировать свои классы с помощью функции инверсии управления и абстрагировать необходимые типы на интерфейсы.
Представьте себе класс, который может получить количество заказов или общую сумму всех заказов, и вы хотите проверить его логику.
public interface IOrdersRepository
{
IEnumerable<Order> GetOrdersForCustomer(Guid customerId);
}
public class OrdersService : IOrdersService
{
private readonly IOrdersRepository ordersRepository;
// pass the orders repository that abstracts the database access
// as a dependency, so your OrdersService can be tested in isolation
public OrdersService(IOrdersRepository ordersRepository)
{
this.ordersRepository = ordersRepository
}
public int GetOrdersCount(Customer customer)
{
return ordersRepository.GetOrdersForCustomer(customer.Id).Count();
}
public decimal GetAllOrdersTotalSum(Customer customer)
{
return ordersRepository.GetOrdersForCustomer(customer.Id).Sum(order => order.TotalSum);
}
}
Затем в тестовом модуле вы могли бы сделать что-то вроде
[Fact]
public void CalculateOrderTotalSumTest()
{
// customer id we want to check
Guid customerId = new Guid("64f52c5c-44b4-4adc-9760-5a03d6f98354");
// Our test data
List<Order> orders = new List<Order>()
{
new Order() { Customer = new Guid("64f52c5c-44b4-4adc-9760-5a03d6f98354"), TotalSum = 100.0m),
new Order() { Customer = new Guid("64f52c5c-44b4-4adc-9760-5a03d6f98354"), TotalSum = 50.0m)
}
// Create a mock of the IOrdersRepository
var ordersRepositoryMock = new Mock<IOrdersRepository>();
// Next you need to set up the mock to return a certain value
ordersRepositoryMock
.Setup(m => m.ordersRepositoryMock(It.Is<Guid>(cId => cId == customerId))
.Returns(orders);
decimal totalSum = ordersRepositoryMock.Object.GetAllOrdersTotalSum(customerId);
Assert.AreEqual(150.0m, totalSum, "Total sum doesn't match expected result of 150.0m");
ordersRepositoryMock.VerifyAll();
}
Таким образом, вы можете проверить свои классы в изоляции без необходимости базы данных. Если вам нужна база данных, файл в файловой системе или сетевое соединение в модульном тесте, то вы плохо работали над созданием своих типов.
Вы хотите написать тесты на единицу или интеграцию? Или, может быть, даже системный тест? – Tseng
На данный момент я просто хочу выполнить единичное тестирование. – eSPiYa
Тогда ответ прост: спроектируйте свои классы таким образом, чтобы вы могли передать насмешливый интерфейс классу, который хотите протестировать. Доступ к базам данных или файлам в модульных тестах является абсолютным бездействием. Единичный тест должен тестировать только единицу кода определенного класса **, а не ** его зависимости – Tseng