Hacer que el código sea interno pero esté disponible para pruebas unitarias de otros proyectos.

StackOverflow https://stackoverflow.com/questions/106907

  •  01-07-2019
  •  | 
  •  

Pregunta

Ponemos todas nuestras pruebas unitarias en sus propios proyectos.Descubrimos que tenemos que hacer que ciertas clases sean públicas en lugar de internas solo para las pruebas unitarias.¿Hay alguna forma de evitar tener que hacer esto?¿Cuáles son las implicaciones para la memoria al hacer las clases públicas en lugar de selladas?

¿Fue útil?

Solución

Si está utilizando .NET, el InternosVisiblePara El atributo de ensamblaje le permite crear ensamblajes "amigos".Estos son ensamblajes específicos con nombres fuertes a los que se les permite acceder a clases internas y miembros del otro ensamblaje.

Tenga en cuenta que esto debe usarse con discreción ya que acopla firmemente los conjuntos involucrados.Un uso común de InternalsVisibleTo es para proyectos de pruebas unitarias.Probablemente no sea una buena opción para usar en ensamblajes de aplicaciones reales, por el motivo indicado anteriormente.

Ejemplo:

[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{

Otros consejos

Si es una clase interna, entonces no debe usarse de forma aislada.Por lo tanto, no deberías probarlo aparte de probar alguna otra clase que haga uso de ese objeto internamente.

Así como no deberías probar miembros privados de una clase, no deberías probar clases internas de una DLL.Esas clases son detalles de implementación de alguna clase de acceso público y, por lo tanto, deben ejercitarse bien mediante otras pruebas unitarias.

La idea es que solo desea probar el comportamiento de una clase porque si prueba los detalles de la implementación interna, sus pruebas serán frágiles.Debería poder cambiar los detalles de implementación de cualquier clase sin interrumpir todas las pruebas.

Si descubre que realmente necesita probar esa clase, es posible que desee volver a examinar por qué esa clase es interna en primer lugar.

para fines de documentación

alternativamente, puede crear una instancia de clase interna utilizando Type.GetType método

ejemplo

//IServiceWrapper is public class which is 
//the same assembly with the internal class 
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
    .CreateInstance(type, new object[1] { /*constructor parameter*/ });

Para el tipo genérico existen diferentes procesos como se muestra a continuación:

var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
     .CreateInstance(genType, new object[1] { /*constructor parameter*/});

Las clases pueden ser tanto públicas como selladas.

Pero no hagas eso.

Puede crear una herramienta para reflexionar sobre clases internas y emitir una nueva clase que acceda a todo mediante la reflexión.MSTest hace eso.

Editar:Quiero decir, si no desea incluir ningún material de prueba en su ensamblaje original;Esto también funciona si los miembros son privados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top