Используя ваш пример, предположим, что у вас есть объект - назовите его Foo
- который требует Shape
и Document
в конструкторе.В этом случае у вас будет две опции:
- Создание фактического
Document
и фактического Shape
, но с использованием данных теста, и отправка этих объектов конструктору во время теста. - Создайте макет
Document
и макет Shape
, используя только те функциональные возможности, которые необходимы для запуска фактически выполненного теста, и отправьте их конструктору для теста.
Если ваши объекты большие и сложные, то первый вариант может стать препятствующим для тестирования, особенно для более крупных проектов, где вы можете не знать внутреннюю работу того, как объекты должны создаваться, или если им требуются определенные параметры (например, закрытые ключи,отпечатки пальцев и т. д.), к которым у вас может не быть доступа.Это действительно становится проблемой, когда вы начинаете использовать внедрение зависимостей.Итак, чтобы обойти это, вы связываете объекты, которые вам нужно обойти, а затем вы создаете фиктивные реализации, которые позволяют вам тестировать их.Конечно, через некоторое время это становится довольно повторяющимся, поэтому Moq существует.
Возвращаясь к примеру, вы можете проверить Foo
примерно так:
public void Foo_TestingFoo_DoesBar()
{
var mockDoc = new Mock<Document>();
var mockShape = new Mock<Shape>();
// "implement" the methods you will need during your test
mockDoc.Setup(...);
mockShape.Setup(...);
// Get the "actual" Document and Shape and use them as arguments to the ctor
var foo = new Foo(mockDoc.Object, mockShape.Object);
// Do stuff with foo
foo.DoBar();
// Verify that these objects were used how you expected them to be
mockDoc.Verify(...);
mockShape.Verify(...);
}