模拟DirectoryEntry的“属性”属性

时间:2013-08-05 10:57:22

标签: c# unit-testing active-directory moq directoryservices

我正在尝试对一些Active Directory代码进行单元测试,与此问题中概述的几乎相同:

Create an instance of DirectoryEntry for use in test

接受的答案建议为DirectoryEntry类实现一个包装器/适配器,我有:

public interface IDirectoryEntry : IDisposable
{
    PropertyCollection Properties { get; }
}

public class DirectoryEntryWrapper : DirectoryEntry, IDirectoryEntry
{
}

问题是我的IDirectoryEntry mock上的“ Properties ”属性未初始化。试图像这样设置模拟:

this._directoryEntryMock = new Mock<IDirectoryEntry>();
this._directoryEntryMock.Setup(m => m.Properties)
                        .Returns(new PropertyCollection());

导致以下错误:

类型'System.DirectoryServices.PropertyCollection'没有定义构造函数

据我所知,当尝试仅使用内部构造函数实例化一个类时会抛出此错误:

The type '...' has no constructors defined

我曾尝试为PropertyCollection类编写一个包装器/适配器但没有公共构造函数我无法弄清楚如何从类中实例化或继承。

那么我如何在DirectoryEntry类上模拟/设置“ Properties ”属性以进行测试?

2 个答案:

答案 0 :(得分:8)

感谢Chris的建议,这里是我最终解决方案的代码示例(我选择了他的选项1):

public interface IDirectoryEntry : IDisposable
{
    IDictionary Properties { get; }
}

public class DirectoryEntryWrapper : IDirectoryEntry
{
    private readonly DirectoryEntry _entry;

    public DirectoryEntryWrapper(DirectoryEntry entry)
    {
        _entry = entry;
        Properties = _entry.Properties;
    }

    public void Dispose()
    {
        if (_entry != null)
        {
            _entry.Dispose();
        }
    }

    public IDictionary Properties { get; private set; }
}

使用如下:

this._directoryEntryMock = new Mock<IDirectoryEntry>();
this._directoryEntryMock
        .Setup(m => m.Properties)
        .Returns(new Hashtable()
        {
            { "PasswordExpirationDate", SystemTime.Now().AddMinutes(-1) }
        });

答案 1 :(得分:3)

我认为您无法模拟或创建PropertyCollection的实例。有一些方法可以克服这个问题,但它们要求您将派生的包装类转换为更多的实际包装器,封装DirectoryEntry对象并提供访问器,而不是扩展它。完成后,您可以选择以下选项:

  1. Properties属性的返回类型定义为PropertyCollection实现的基础集合类型之一(IDictionaryICollectionIEnumerable),如果这足以满足您的需求
  2. 使用PropertyCollection的接口创建一个封装包装类,并在每次调用directoryEntry.Properties访问者时创建一个新的包装Properties
  3. IDirectoryEntry / DirectoryEntryWrapper上创建方法,返回您需要的内容,而不必公开Properties属性
  4. 如果您可以通过其中一种基础集合类型访问属性,那么

    1可能是一种解决方法。 2将要求您在包装器中实现PropertiesCollection的每个方法和属性,调用下面的封装对象,但是最灵活。最简单(但最不灵活)是3。