Как правило, вы не хотите создавать DI-контейнер для своих тестов, но, как вы понимаете, вместо этого вы хотите имитировать их. Так, например, если это класс, который вы хотите проверить:
public class UserService
{
private readonly IUserDatabase _userDatabase;
public UserService(IUserDatabase userDatabase)
{
_userDatabase = userDatabase;
}
public bool DoesUserExist(int userId)
{
return _userDatabase.UserExists(userId);
}
}
И это определение используемого интерфейса:
public interface IUserDatabase
{
bool UserExists(int userId);
}
В наших тестах мы можем смоделировать интерфейс, чтобы вернуть определенное значение, которое мы хотим для нашего теста:
[TestClass]
public class UserServiceTests
{
[TestMethod]
public void DoesUserExist_ForValidUserId_ReturnsTrue()
{
var fakeUserId = 123;
var mockUserDatabase = new Mock<IUserDatabase>();
mockUserDatabase.Setup(udb => udb.UserExists(fakeUserId)).Returns(true);
var userService = new UserService(mockUserDatabase.Object);
var result = userService.DoesUserExist(fakeUserId);
Assert.IsTrue(result);
mockUserDatabase.VerifyAll();
}
}
Итак, в этом тесте мы использовали Moq
для создания макета нашего интерфейса. Нам не нужно использовать DI-контейнер, потому что мы находимся в контроллере создания класса, который мы тестируем. Контейнер DI более широко используется в производстве, поскольку он позволяет приложению создавать любые необходимые ему зависимости без вызова кода new
- что является большой проблемой, если вы пытаетесь выполнить модульное тестирование своих классов.
Метод .VerifyAll()
проверяет, действительно ли были вызваны любые методы, настроенные для фиктивного объекта, в данном случае мы устанавливаем вызов UserExists
.
Существует множество примеров того, как использовать Moq
и интерфейсы для насмешек в целом.
Краткое руководство по Moq
здесь здесь