Mocking the “Properties” property of DirectoryEntry

末鹿安然 提交于 2019-12-06 09:23:39

问题


I'm trying to unit test some Active Directory code, pretty much the same as outlined in this question:

Create an instance of DirectoryEntry for use in test

The accepted answer suggests implementing a wrapper/adapter for the DirectoryEntry class, which I have:

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

public class DirectoryEntryWrapper : DirectoryEntry, IDirectoryEntry
{
}

The problem is that the "Properties" property on my IDirectoryEntry mock is not initialised. Trying to set the mock up like this:

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

Results in the following error:

The type 'System.DirectoryServices.PropertyCollection' has no constructors defined

As I understand it, this error is thrown when trying to instantiate a class with internal constructors only:

The type '...' has no constructors defined

I have tried to write a wrapper/adapter for the PropertyCollection class but without a public constructor I can't figure out how to instantiate or inherit from the class.

So how can I mock/setup the "Properties" property on the DirectoryEntry class for testing purposes?


回答1:


I don't think that you'll be able to mock or create an instance of PropertyCollection. There are ways of overcoming this, but they require you to convert your derived wrapper class to be more of an actual wrapper, encapsulating a DirectoryEntry object and providing accessors, not extending it. Once you've done that, you have these options:

  1. Define the return type of the Properties property as one of the underlying collection types that PropertyCollection implements (IDictionary, ICollection or IEnumerable), if that is sufficient for your needs
  2. Create an encapsulating wrapper class with an interface for PropertyCollection, and create a new one to wrap directoryEntry.Properties each time the Properties accessor is called
  3. Create methods on IDirectoryEntry/DirectoryEntryWrapper that return what you need without having to expose a Properties property

1 might be fine as a workaround, if you're OK accessing the properties through one of the underlying collection types. 2 will require you to implement every method and property of PropertiesCollection in the wrapper, calling through to the encapsulated object underneath, but would be the most flexible. The easiest (but least flexible) is 3.




回答2:


Thanks to Chris's suggestions here is a code sample for my eventual solution (I went with his option 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; }
}

Used as follows:

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


来源:https://stackoverflow.com/questions/18056483/mocking-the-properties-property-of-directoryentry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!