Изолирование кода во время тестирования с помощью Microsoft Fakes (Shims)

в 13:21, , рубрики: .net, fakes, microsoft, microsoft fakes, shim, shims, unit test, unit tests, тестирование

Впервые я встретился с юнит тестированием на Java и был рад возможности делать моки на final классы, на статические члены. В это время на .Net нельзя было сделать ничего подобного. Только интерфейсы. Можно безгранично долго рассуждать о том, что если понадобилось делать что-то неестественное, то нужно переписывать реализацию, делать IOC и прочее. Но когда речь идет о наследованном коде, неприспособленном архитектурно к юнит тестированию – возможность менять вещи без переписывания выручает.
Я окончательно забросил Java и ушел в .Net и каждый раз при разговоре о юнит тестах вспоминал, что на Java возможностей больше.
И вот в 2012 студии добавили возможность делать мок любых объектов. Абсолютно любых, даже системных. Под катом перевод статьи из MSDN (переведено только по шимам, т.к. стабы особого интереса не представляют).

Microsoft использует термин “shim”, я не буду пытаться его переводить, пускай так и будет – шим.

Что такое шимы
Microsoft Fakes помогает изолировать тестируемый код двумя смособами – шимы и стабы.
Шимы модифицируют скомпилированный код в рантайме, так что вызов метода подменяется вызовом кода, который вы написали. Шимы могут использоваться для подмены вызовов сборок, которыми вы не можете управлять, например сборками .Net Framework'а.
image

Выбор между стабами и шимами
Обычно проект в VS разрабатывается как отдельный компонент и есть желание использовать стабы или шимы для используемых объектов из других проектов в солюшене или внешних сборок, на которые проект ссылается.
Старайтесь использовать стабы для кода, который находятся внутри солюшина, а шимы для внешних сборок. Считается хорошей практикой декомпозировать элементы, выделяя интерфейсы, что позволяет использовать стабы, но внешние сборки, такие как System.dll обычно не имеют такой декомпозиции, поэтому вы должны использовать шимы.

Использование
Представьте, что ваш компонент имеет вызов DateTime.Now:

// Code under test:
public int GetTheCurrentYear()
{
    return DateTime.Now.Year;
}

Во время теста вы хотите сделать шим свойста Now, т.к. оригинал всегдя возвращает разные значения
Для использования шимом вам не нужно модифицировать код или писать его определенным образом.

1. Добавление фейковой сборки
В Solution Explorer откройте references вашего проекта и выберите сборку в которй находятся классы, которые вы хотите подменить. Класс DateTime находитс в сборке System.dll. и в контекстном меню выберите “ Add Fakes Assembly ”.

2. Использование шимов внутри ShimsContext

    [TestClass]
    public class TestClass1
    { 
            [TestMethod]
            public void TestCurrentYear()
            {
                int fixedYear = 2000;

                // Shims can be used only in a ShimsContext:
                using (ShimsContext.Create())
                {
                  // Arrange:
                    // Shim DateTime.Now to return a fixed date:
                    System.Fakes.ShimDateTime.NowGet = 
                    () =>
                    { return new DateTime(fixedYear, 1, 1); };

                    // Instantiate the component under test:
                    var componentUnderTest = new MyComponent();

                  // Act:
                    int year = componentUnderTest.GetTheCurrentYear();

                  // Assert: 
                    // This will always be true if the component is working:
                    Assert.AreEqual(fixedYear, year);
                }
            }
    }

Имена шим классов начинаются с префикса Fakes.Shim, добавляемого к оригинальным именам.
В примере шим используется для стаического метода, для использования шима для не статического метода добавте AllInstances между именем типа и именем метода:

System.IO.Fakes.ShimFile.AllInstances.ReadToEnd = ...

Шимы также можно создавать для конкретных объектов, конструкторов, свойств.

Если данный перевод окажется интересным людям, то я сделаю перевод следующей статьи, где приведены примеры использования шимов для всех случаев.

Автор: igofed

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js