Библиотека для создания класса, который имеет встроенный конструктор в другой сборке со случайными данными?
Я получаю уведомления о событиях от веб-служб, которые запускают обработчики событий с данными о том, что вызвало событие. Я пытаюсь проверить, как только обработчик события называется a
, b
а также c
все вызываются с правильными значениями. Это невозможно без использования веб-службы.
Мое решение заключается в создании конвертеров, которые преобразуют EventArgs
которые возвращаются мне через библиотеку служб (веб-службы Exchange), что-то, что мои тупые объекты могут понять, не полагаясь на службы третьей части. Моя проблема в том, что EventArgs
Класс, данный my библиотекой EWS, имеет внутренний конструктор, поэтому нет простого способа создать его экземпляр со случайными значениями свойств без особой работы с отражением.
Например, у меня есть простой интерфейс:
public interface IConverter<TFrom, TTo>
{
TTo Convert(TFrom from);
}
и простая реализация:
public class NotificationEventArgsConverter : IConverter<NotificationEventArgs, NewNotification>
{
public NewNotification Convert(NotificationEventArgs from)
{
return new NewNotification
{
ItemIds = from.Events.Cast<ItemEvent>().Select(x => x.ItemId.ToString())
};
}
}
Вопрос в том, как я могу создать экземпляр NotificationEventArgs
со случайными значениями. Есть ли библиотека для этого, которую я пропустил в своих поисках?
Вся цель этого состоит в том, чтобы подражать, если я получаю экземпляр NotificationEventArgs
со следующими значениями тогда NewNotification
должен напоминать x
,
редактировать
А пока я просто буду использовать typeof(T).GetConstructor()
,
2 ответа
Возможно, вы захотите взглянуть на AutoFixture:
AutoFixture облегчает разработчикам разработку через тестирование, автоматизируя несоответствующую настройку Test Fixture, позволяя разработчику тестов сосредоточиться на основных моментах каждого теста.
Выполнив некоторую декомпиляцию Microsoft.Exchange.WebServices и поиграв с отражением, вы можете сделать это, например, так:
var fixture = new Fixture();
// retrieve internal FolderEvent(EventType, DateTime) ctor
// using FolderEvent class as NotificationEvent is abstract
var notificationEventCtor = typeof(FolderEvent).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[] { typeof(EventType), typeof(DateTime) },
null
);
// generate 10 random events with some help of LINQ and AutoFixture
var trashData = Enumerable
.Range(1, 10)
.Select(i => new object[]
{
fixture.CreateAnonymous<EventType>(),
fixture.CreateAnonymous<DateTime>()
})
.Select(p => notificationEventCtor.Invoke(p))
.Cast<NotificationEvent>()
.ToList();
Код выше сгенерирует 10 FolderEvents
в списке, готовы перейти к NotificationEventArgs
конструктор (который снова является внутренним, поэтому применяется тот же код):
var notificationEventArgsCtor = typeof(NotificationEventArgs).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[]
{
typeof(StreamingSubscription),
typeof(IEnumerable<NotificationEvent>)
},
null
);
var instance = notificationEventArgsCtor
.Invoke(new object[] { null, trashData });
Взгляните на класс PrivateObject (в частности, эти перегрузки конструктора). Он оборачивает всю работу по отражению для вас и позволяет создавать объекты с непубличными конструкторами, а также получать доступ к закрытым методам и свойствам этих объектов. Вы можете получить базовые объекты через свойство Target.