2

我正在从 Web 服务接收事件通知,这些通知会触发事件处理程序,其中包含有关触发事件的数据。一旦事件处理程序被调用,我正在尝试测试它ab并且c都使用正确的值调用。如果不依赖 Web 服务,这是不可能的

我的解决方案是创建转换器,将EventArgs通过服务库(Exchange Web 服务)返回给我的内容转换为我的哑对象可以在依赖第三方服务的情况下理解的内容。我的问题是EventArgsEWS 库提供给我的类有一个内部构造函数,因此没有简单的方法来生成具有随机属性值的实例,而无需进行大量反射工作。

例如,我有一个简单的界面:

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().

4

2 回答 2

2

您可能想看看AutoFixture

AutoFixture 通过自动化不相关的测试夹具设置使开发人员更容易进行测试驱动开发,允许测试开发人员专注于每个测试用例的基本要素。

在对 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 });
于 2012-04-10T14:10:49.873 回答
1

看看PrivateObject类(特别是这些构造函数 重载)。它为您包装了所有反射工作,并允许您使用非公共构造函数创建对象,以及访问这些对象的非公共方法和属性。您可以通过Target属性获取基础对象。

于 2012-04-10T19:22:30.023 回答