Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking the "Properties" property of DirectoryEntry

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?

like image 492
Brett Postin Avatar asked Aug 05 '13 10:08

Brett Postin


2 Answers

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) }
        });
like image 120
Brett Postin Avatar answered Sep 28 '22 01:09

Brett Postin


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.

like image 40
Chris Mantle Avatar answered Sep 28 '22 01:09

Chris Mantle