que publicas protegidas propiedades programacion privadas privada operadores niveles modificador encapsulamiento clases clase autoimplementadas acceso c# unit-testing mstest

c# - publicas - que es public en programacion



¿Cómo puedo usar PrivateObject para acceder a miembros privados tanto de mi clase como de su padre? (7)

Como escribió André Pena. ¿Por qué le gustaría probar miembros private de la clase de base a través de la subclase? Tampoco tendría acceso a estos miembros en el código normal de su Subclase. Debe hacer que los miembros de las Propiedades estén protected para tener acceso a ellos desde la Subclase.

Entonces también puedes probar a estos miembros con el PrivateObject.

Estoy probando una clase que es parte de una jerarquía. He estado configurando mis clases de prueba con el objeto bajo prueba, y un PrivateObject para permitir el acceso a ese objeto. Recibo excepciones cuando intento acceder a miembros privados de la clase padre.

La única solución que he encontrado hasta ahora es pasar un PrivateType especificando la clase base al constructor PrivateObject , pero luego no funciona en los miembros privados de la subclase.

¿Hay alguna forma en que pueda hacer esto, tal vez utilizando el parámetro de banderas de enlace en los métodos Get * del objeto privado?

Intenté usar las clases de Accessor generadas automáticamente (haga clic con el botón derecho en la clase principal, Create Private Accessor). Sin embargo, eso es peor: muestra una propiedad que puedo leer, pero arroja la misma excepción que PrivateObject, y no hay otras opciones que pueda usar (banderas de enlace o lo que sea) para corregir la excepción.

Aquí está mi código de prueba de muestra. Me gustaría que hubiera alguna forma de construir y usar PrivateObject para recuperar ambos campos.

public class BaseClass { private int one = 1; } public class SubClass : BaseClass { private int two = 2; } [TestClass] public class UnitTest1 { BindingFlags flags = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; [TestMethod] public void TestMethod1() { SubClass test = new SubClass(); PrivateObject priv = new PrivateObject(test); Assert.AreNotEqual<int>(0, (int)priv.GetFieldOrProperty("one", flags)); // System.MissingMethodException: Method ''PrivateObjectTester.SubClass.one'' not found. Assert.AreNotEqual<int>(0, (int)priv.GetFieldOrProperty("two", flags)); } [TestMethod] public void TestMethod2() { SubClass test = new SubClass(); PrivateObject priv = new PrivateObject(test, new PrivateType(typeof(BaseClass))); Assert.AreNotEqual<int>(0, (int)priv.GetFieldOrProperty("one", flags)); Assert.AreNotEqual<int>(0, (int)priv.GetFieldOrProperty("two", flags)); // System.MissingMethodException: Method ''PrivateObjectTester.BaseClass.two'' not found. } }


Es probable que esta no sea la respuesta que desea ... pero, en primer lugar, no debería probar ambas clases en un método. Solo deberías estar probando una clase a la vez. Si siente la necesidad de hacer esto, entonces supongo que su código necesita refactorización. Pero como no conozco el problema del código de la vida real, no puedo asegurarlo.


No encontré la respuesta, así que esto es lo que terminé haciendo. PrivateObjects para cada nivel de la jerarquía de la clase, y solo necesito tener cuidado al escribir los casos de prueba que uso el adecuado.

public class BaseClass { private int one = 1; } public class SubClass : BaseClass { private int two = 2; } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod() { SubClass test = new SubClass(); PrivateObject privSub = new PrivateObject(test, new PrivateType(typeof(SubClass))); PrivateObject privBase = new PrivateObject(test, new PrivateType(typeof(BaseClass))); Assert.AreNotEqual<int>(0, (int)privBase.GetFieldOrProperty("one")); Assert.AreNotEqual<int>(0, (int)privSub.GetFieldOrProperty("two")); } }


PrivateObject está un poco en el lado "tonto" cuando se trata de manejar la herencia. Desafortunadamente, sus métodos no son virtuales, por lo que no hay una manera fácil de cambiar este comportamiento. Básicamente, tiene dos opciones: vivir con las limitaciones o crear su propio ayudante de acceso privado que pueda manejar los miembros heredados de manera transparente.


Quería hacer lo mismo e hice los métodos de esta extensión. Ahora funciona bien. Mi idea inicial es de tu post. ¡Gracias!

https://github.com/cactuaroid/PrivateObjectExtensions

Básicamente, lo que está haciendo es encontrar el propietario del miembro por Type.GetFields() y Type.GetProperties() recursivamente, y luego crear PrivateObject (o PrivateType) como tipo correcto para acceder al miembro.


Use PrivateType para especificar el tipo deseado y use un constructor diferente de PrivateObject :

var test = new SubClass(); var privateType = new PrivateType(typeof(BaseClass)); var privateObject = new PrivateObject(test, privateType); // privateObject.GetFieldOrProperty("one", flags)


// create an instance of class SearchPlanogramsBuilder: SearchPlanogramsBuilder searchPlanogramBuilder = new SearchPlanogramsBuilder(); // executing the method BuildSearchParameters(return type is void) with input searchPlanoGramsFilters: searchPlanogramBuilder.BuildSearchParameters(searchPlanoGramsFilters); // create privateobject and pass instance created for the class: PrivateObject helperobject1 = new PrivateObject(searchPlanogramBuilder); // type cast exactly as parameter(which is private variable) in the method: Collection<string> parameter = (Collection<string>)helperobject1.GetFieldOrProperty("parameters");