Как правильно настроить модульные тесты C# для плагинов CRM 2011?

Попытка отладки плагина в CRM 2011 может быть чрезвычайно сложной. Существуют не только проблемы с наличием файлов.pdb в правильном месте на сервере, но каждый раз, когда вы вносите изменения в кодировку, вы сталкиваетесь с трудностями развертывания и перерегистрации плагина. Поскольку триггер находится в самой CRM, для него сложно создать модульный тест.

Мой текущий процесс написания модульного теста для нового плагина довольно медленный и с ошибками, но идет примерно так:

  1. Зарегистрируйте новый плагин с помощью инструмента регистрации плагинов SDK.
  2. Присоедините отладчик к w3wp.exe, установив точку останова в коде плагина.
  3. Запустите плагин через любое действие, для которого он зарегистрирован.
  4. Когда достигается точка останова, сериализуются значения preimage, postimage и target конвейера в XML-файлы, это становится входом для моего модульного теста.
  5. Остановите отладку и создайте новый модульный тест, используя RhinoMocks для насмешки над PluginExecutionContext и ServiceProvider, используя загрузку сериализованных файлов XML в качестве заглушек для входных параметров.
  6. Создайте методы, которые запускаются в начале и в конце каждого модульного теста, который сбрасывает (сначала пытается удалить, затем добавляет) фиктивные данные для обработки модульного теста, а затем удаляет фиктивные данные в конце теста.
  7. Отредактируйте Сериализованные файлы, чтобы они ссылались на фиктивные данные, чтобы я мог гарантировать, что плагин будет работать с одними и теми же данными при каждом запуске.
  8. Объявите и создайте экземпляр плагина в модульном тесте, передавая имитируемые объекты
  9. Запустите плагин, запустив дополнительные запросы, чтобы убедиться, что плагин выполнил ожидаемую мной работу, утверждая, что произошел сбой.

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

Как я могу провести модульное тестирование плагина, не вызывая его на самом деле из CRM, или не пройдя через все препятствия сначала отладки в CRM и создания уникальных фиктивных данных для каждого теста? Как я могу использовать инъекцию, чтобы избавить от необходимости удалять, создавать, тестировать, проверять и удалять данные в CRM для каждого модульного теста?

Обновление 2016

Этот вопрос до сих пор встречает немало хитов, поэтому я подумал, что я бы добавил два (известных мне) двух проектов с открытым исходным кодом, которые предоставляют экземпляры Fake CRM для модульного тестирования:

  • FakeXrmEasy - Создано Jordi (см. Ответ ниже)
    • В первую очередь поддельный CRM сервис
    • Поддержка плагинов / подделок рабочих процессов
    • Зависимость от FakeItEasy
    • Отличная документация
  • XrmUnitTest - Создано мной
    • Поддельная служба CRM + еще (предположения, Entity Builders и т. Д.)
    • Свободная поддержка подделки плагинов / рабочих процессов
    • Нет зависимости от насмешек
    • Отстойная документация (я работаю над этим)

Оформить заказ видео, которое я создал, чтобы сравнить и сопоставить различия.

3 ответа

Решение

Как я могу провести модульное тестирование плагина, не вызывая его на самом деле из CRM, или не пройдя через все препятствия сначала отладки в CRM и создания уникальных фиктивных данных для каждого теста?

С издевательством. Посмотрите эту ссылку, чтобы узнать, какие классы можно издеваться с RhinoMocks Похоже, вы на этом пути.

Как я могу использовать инъекцию, чтобы избавить от необходимости удалять, создавать, тестировать, проверять и удалять данные в CRM для каждого модульного теста?

Внедрение значений для входных параметров может быть выполнено путем создания заглушки в проверенном вручную экземпляре объекта, которым вы собираетесь манипулировать:

// Add the target entity     
Entity myStubbedEntity = new Entity("account");
// set properties on myStubbedEntity specific for this test...
ParameterCollection inputParameters = new ParameterCollection();     
inputParameters.Add("Target", myStubbedEntity);     
pipelineContext.Stub(x => x.InputParameters).Return(inputParameters); 

Разве это не проще, чем захват XML-данных и повторное увлажнение всей коллекции входных параметров?


РЕДАКТИРОВАТЬ: для доступа к данным обычная рекомендация состоит в том, чтобы обернуть доступ к данным в классы. Шаблон репозитория популярен, но излишним для того, что нам нужно здесь. Для классов исполнения ваших плагинов, вы "внедряете" свой смоделированный класс при создании. Пустой конструктор, который инициализирует репозиторий по умолчанию, и второй конструктор, который принимает IRepository.

public class MyPluginStep
{
    ITaskRepository taskRepository;
    public MyPluginStep(ITaskRepository repo)
    {
        taskRepository = repo;
    }
    public MyPluginStep()
    {
        taskRepository = new DefaultTaskRepositoryImplementation();
    }
    public MyExecuteMethod(mypluginstepparams){
        Task task = taskRepository.GetTaskByContact(...);
    }

В зависимости от сложности шагов вашего плагина это может перерасти в передачу множества репозиториев каждому классу и может стать обременительным, но это основы, к которым вы можете добавить сложность, если это необходимо.

Я сериализую контекст выполнения плагина в файл для использования с юнит-тестами. Есть хороший проект на codeplex, который делает это http://crm2011plugintest.codeplex.com/

Упрощает отладку и модульное тестирование, и вы можете "записывать" тестирование в реальном мире.

Одним из действительно хороших вариантов было бы использование библиотеки-макета, которая имеет дело с макетами и подделками для вас, потому что я хотел создать свой собственный и всегда заканчивал тем, что тратил много времени на создание фальшивок или подделок, пока я не создал эту библиотеку, которая делает это для вас. Попробуйте FakeXrmEasy

Другие вопросы по тегам