¿Cómo simularse System.DirectoryServices.SearchResult?

Si tiene un método que necesita ser probado que toma una lista de SearchResults

public virtual void ProcessResults(IList list) { //Code to tests here } 

¿Cómo te burlas de esa lista de SearchResult?

Nota: No se permiten marcos de inyección de bajo nivel (por ejemplo, TypeMock).

Actualmente tengo este código feo

 public static class SearchResultFactory { const BindingFlags nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance; const BindingFlags publicInstance = BindingFlags.Public | BindingFlags.Instance; public static SearchResult Construct(T anonInstance) { var searchResult = GetUninitializedObject(); SetPropertiesFieled(searchResult); var dictionary = (IDictionary)searchResult.Properties; var type = typeof(T); var propertyInfos = type.GetProperties(publicInstance); foreach (var propertyInfo in propertyInfos) { var value = propertyInfo.GetValue(anonInstance,null); var propertyCollection = GetUninitializedObject(); var innerList = GetInnerList(propertyCollection); if (propertyInfo.PropertyType.IsArray) { var stringArray = (String[])value; foreach (var subValue in stringArray) { innerList.Add(subValue); } } else { innerList.Add(value); } var lowerKey = propertyInfo.Name.ToLower(CultureInfo.InvariantCulture); dictionary.Add(lowerKey, propertyCollection); } return searchResult; } private static ArrayList GetInnerList(object resultPropertyCollection) { var propertyInfo = typeof(ResultPropertyValueCollection).GetProperty("InnerList", nonPublicInstance); return (ArrayList) propertyInfo.GetValue(resultPropertyCollection, null); } private static void SetPropertiesFieled(SearchResult searchResult) { var propertiesFiled = typeof(SearchResult).GetField("properties", nonPublicInstance); propertiesFiled.SetValue(searchResult, GetUninitializedObject()); } private static T GetUninitializedObject() { return (T) FormatterServices.GetUninitializedObject(typeof(T)); } } 

que se utiliza …

 var searchResult = SearchResultFactory.Construct( new { name = "test1", givenName = "John", sn = "Smith", rights = new String[] { "READ", "WRITE" } }); 

, Si va a realizar cualquier cantidad de progtwigción de AD y desea poder probarlo, considere escribir un envoltorio que pueda usar en lugar de BOTH SearchResult y DirectoryEntry; de esa manera, como un beneficio adicional, no lo hace. tiene que escribir dos de cada función que necesitaría tomar un SearchResult o DirectoryEntry.

Hice algo similar a esto. No fue exactamente un proyecto de una sola noche, pero valió la pena dado que estaba trabajando en un producto ISV AD. Probablemente puedas envolver menos y disminuir el esfuerzo. Aquí hay un diseño de pseudocódigo para darle una idea:

  DirectoryObject : IDirectoryObject, IDisposable (Important!) ctor (DirectoryEntry) ctor (SearchResult) ctor (string Path) string Path bool IsValid Search(with a gazillion overloads) DirectoryObjectPropertyCollection Properties //(which itself uses DirectoryObjectPropertyValueCollection to wrap PropertyValueCollection) //To get at the native underlying objects if necessary since I only wrapped commonly used elements DirectoryEntry NativeDirectoryEntry SearchResult NativeSearchResult //So I know whether to grab the native SearchResult or DirectoryEntry IsDirectoryEntry IsSearchResult 

Este enfoque, además del aumento de la capacidad de prueba, me evita tener que hacer cosas como las siguientes en nuestras bibliotecas compartidas:

  public void DoSomethingWithAUser(DirectoryEntry user,...) public void DoSomethingWithAUser(SearchResult user,...) public void DoSomethingWithAUser(string userPath,...) 

y ahora solo tenemos

  public void DoSomethingWithAUser(DirectoryObject user,...) 

Podría escribir su propia clase de envoltura alrededor del SearchResult, implementar alguna interfaz ISearchResult.

Su implementación concreta utiliza la clase SearchResult exponiendo internamente todo lo que necesita, y luego puede burlarse de la Interfaz en las pruebas.