问题
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:
- Define the return type of the
Properties
property as one of the underlying collection types thatPropertyCollection
implements (IDictionary
,ICollection
orIEnumerable
), if that is sufficient for your needs - Create an encapsulating wrapper class with an interface for
PropertyCollection
, and create a new one to wrapdirectoryEntry.Properties
each time theProperties
accessor is called - Create methods on
IDirectoryEntry
/DirectoryEntryWrapper
that return what you need without having to expose aProperties
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