模拟DirectoryEntry的"属性"属性

Bre*_*tin 3 c# directoryservices unit-testing moq active-directory

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

创建DirectoryEntry实例以用于测试

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

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

public class DirectoryEntryWrapper : DirectoryEntry, IDirectoryEntry
{
}
Run Code Online (Sandbox Code Playgroud)

问题是我的mock 上的" Properties "属性IDirectoryEntry没有初始化.试图像这样设置模拟:

this._directoryEntryMock = new Mock<IDirectoryEntry>();
this._directoryEntryMock.Setup(m => m.Properties)
                        .Returns(new PropertyCollection());
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

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

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

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

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

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

Bre*_*tin 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; }
}
Run Code Online (Sandbox Code Playgroud)

使用如下:

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


Chr*_*tle 4

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

  1. 将属性的返回类型定义Properties为实现PropertyCollection(IDictionaryICollectionIEnumerable(如果这足以满足您的需求)
  2. 创建一个带有 接口的封装包装类,并在每次调用访问器时PropertyCollection创建一个新的包装类directoryEntry.PropertiesProperties
  3. IDirectoryEntry在/上创建方法DirectoryEntryWrapper来返回您需要的内容,而无需公开Properties属性

如果您可以通过一种底层集合类型访问属性,那么 1 可能是一种解决方法。2 将要求您实现PropertiesCollection包装器中的每个方法和属性,调用下面的封装对象,但这将是最灵活的。最简单(但最不灵活)的是 3。