Как правильно настроить модульные тесты C# для плагинов CRM 2011?
Попытка отладки плагина в CRM 2011 может быть чрезвычайно сложной. Существуют не только проблемы с наличием файлов.pdb в правильном месте на сервере, но каждый раз, когда вы вносите изменения в кодировку, вы сталкиваетесь с трудностями развертывания и перерегистрации плагина. Поскольку триггер находится в самой CRM, для него сложно создать модульный тест.
Мой текущий процесс написания модульного теста для нового плагина довольно медленный и с ошибками, но идет примерно так:
- Зарегистрируйте новый плагин с помощью инструмента регистрации плагинов SDK.
- Присоедините отладчик к w3wp.exe, установив точку останова в коде плагина.
- Запустите плагин через любое действие, для которого он зарегистрирован.
- Когда достигается точка останова, сериализуются значения preimage, postimage и target конвейера в XML-файлы, это становится входом для моего модульного теста.
- Остановите отладку и создайте новый модульный тест, используя RhinoMocks для насмешки над PluginExecutionContext и ServiceProvider, используя загрузку сериализованных файлов XML в качестве заглушек для входных параметров.
- Создайте методы, которые запускаются в начале и в конце каждого модульного теста, который сбрасывает (сначала пытается удалить, затем добавляет) фиктивные данные для обработки модульного теста, а затем удаляет фиктивные данные в конце теста.
- Отредактируйте Сериализованные файлы, чтобы они ссылались на фиктивные данные, чтобы я мог гарантировать, что плагин будет работать с одними и теми же данными при каждом запуске.
- Объявите и создайте экземпляр плагина в модульном тесте, передавая имитируемые объекты
- Запустите плагин, запустив дополнительные запросы, чтобы убедиться, что плагин выполнил ожидаемую мной работу, утверждая, что произошел сбой.
Это боль, чтобы сделать. От получения правильных изображений до создания фиктивных данных и их сброса при каждом запуске теста, кажется, есть много областей для улучшения.
Как я могу провести модульное тестирование плагина, не вызывая его на самом деле из 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