Tengo una prueba unitaria (nUnit). En muchas capas de la pila de llamadas, un método fallará si se ejecuta mediante una prueba unitaria.
Idealmente, usaría algo como burlarse para configurar el objeto del que depende este método, pero este es un código de terceros y no puedo hacerlo sin mucho trabajo.
No quiero configurar métodos específicos de nUnit: hay demasiados niveles aquí y es una mala manera de hacer la prueba unitaria.
En cambio, lo que me gustaría hacer es agregar algo como esto en el fondo de la pila de llamadas
#IF DEBUG // Unit tests only included in debug build
if (IsRunningInUnitTest)
{
// Do some setup to avoid error
}
#endif
Entonces, ¿alguna idea sobre cómo escribir IsRunningInUnitTest?
PD: Soy plenamente consciente de que este no es un gran diseño, pero creo que es mejor que las alternativas.
c#
reflection
nunit
Ryan
fuente
fuente
Respuestas:
He hecho esto antes, tuve que taparme la nariz mientras lo hacía, pero lo hice. El pragmatismo siempre gana al dogmatismo. Por supuesto, si no es una buena manera se puede refactorizar para evitarlo, que sería grande.
Básicamente, tenía una clase "UnitTestDetector" que verificaba si el ensamblaje del marco NUnit estaba cargado en el AppDomain actual. Solo necesitaba hacer esto una vez, luego almacenar en caché el resultado. Feo, pero sencillo y eficaz.
fuente
AppDomain.GetAssemblies
y verificaría el ensamblaje relevante; para MSTest, necesitaría ver qué ensamblajes están cargados. Mira la respuesta de Ryan para ver un ejemplo.Tomando la idea de Jon, esto es lo que se me ocurrió:
Silencio desde atrás, todos somos chicos lo suficientemente grandes como para reconocer cuando estamos haciendo algo que probablemente no deberíamos hacer;)
fuente
Adaptado de la respuesta de Ryan. Éste es para el marco de pruebas unitarias de MS.
La razón por la que necesito esto es porque muestro un cuadro de mensaje en los errores. Pero mis pruebas unitarias también prueban el código de manejo de errores, y no quiero que aparezca un MessageBox al ejecutar las pruebas unitarias.
Y aquí hay una prueba unitaria para ello:
fuente
Simplificando la solución de Ryan, puede agregar la siguiente propiedad estática a cualquier clase:
fuente
Utilizo un enfoque similar al de tallseth
Este es el código básico que podría modificarse fácilmente para incluir el almacenamiento en caché. Otra buena idea sería agregar un establecedor
IsRunningInUnitTest
y llamarUnitTestDetector.IsRunningInUnitTest = false
al punto de entrada principal de su proyecto para evitar la ejecución del código.fuente
Quizás útil, verificando ProcessName actual:
Y esta función también debe ser verificada por unittest:
Referencias:
Matthew Watson en http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/11e68468-c95e-4c43-b02b-7045a52b407e/
fuente
|| processName.StartsWith("testhost") // testhost.x86
para VS 2019En modo de prueba,
Assembly.GetEntryAssembly()
parece sernull
.Tenga en cuenta que si lo
Assembly.GetEntryAssembly()
esnull
,Assembly.GetExecutingAssembly()
no lo es.La documentación dice: El
GetEntryAssembly
método puede regresarnull
cuando se ha cargado un ensamblado administrado desde una aplicación no administrada.fuente
En algún lugar del proyecto que se está probando:
En algún lugar de su proyecto de prueba unitaria:
Elegante, no. Pero sencillo y rápido.
AssemblyInitializer
es para MS Test. Esperaría que otros marcos de prueba tuvieran equivalentes.fuente
IsRunningInUnitTest
no se establece como verdadero en esos AppDomains.Utilizo esto solo para omitir la lógica que deshabilita todos los TraceAppenders en log4net durante el inicio cuando no hay un depurador adjunto. Esto permite que las pruebas unitarias se registren en la ventana de resultados de Resharper incluso cuando se ejecutan en modo sin depuración.
El método que utiliza esta función se llama al inicio de la aplicación o al iniciar un dispositivo de prueba.
Es similar a la publicación de Ryan pero usa LINQ, elimina el requisito System.Reflection, no almacena en caché el resultado y es privado para evitar un uso indebido (accidental).
fuente
Tener una referencia al marco nunit no significa que la prueba se esté ejecutando. Por ejemplo, en Unity, cuando activa las pruebas del modo de reproducción, las referencias de nunit se agregan al proyecto. Y cuando ejecutas un juego, las referencias existen, por lo que UnitTestDetector no funcionaría correctamente.
En lugar de verificar el ensamblaje de nunit, podemos pedirle a la api de nunit que verifique si el código se está ejecutando ahora o no.
Editar:
Tenga en cuenta que TestContext se puede generar automáticamente si es necesario.
fuente
Solo usa esto:
En el modo de prueba, devolverá falso.
fuente
No estaba contento de tener este problema recientemente. Lo resolví de una manera ligeramente diferente. Primero, no estaba dispuesto a asumir que el marco nunit nunca se cargaría fuera de un entorno de prueba; Estaba particularmente preocupado por los desarrolladores que ejecutaban la aplicación en sus máquinas. En su lugar, recorrí la pila de llamadas. En segundo lugar, pude suponer que el código de prueba nunca se ejecutaría en binarios de lanzamiento, así que me aseguré de que este código no existiera en un sistema de lanzamiento.
fuente
Funciona de maravilla
.
fuente
Las pruebas unitarias omitirán el punto de entrada de la aplicación. Al menos para wpf,
main()
no se llama a winforms ni a la aplicación de consola .Si se llama al método principal, entonces estamos en tiempo de ejecución ; de lo contrario, estamos en modo de prueba unitaria :
fuente
Teniendo en cuenta que su código se ejecuta normalmente en el hilo principal (gui) de una aplicación de formularios de Windows y desea que se comporte de manera diferente mientras se ejecuta en una prueba que puede verificar
Estoy usando esto para el código que quiero
fire and forgot
en una aplicación de interfaz gráfica de usuario, pero en las pruebas unitarias podría necesitar el resultado calculado para una afirmación y no quiero meterme con varios subprocesos en ejecución.Funciona para MSTest. La ventaja es que mi código no necesita verificar el marco de prueba en sí y si realmente necesito el comportamiento asíncrono en una prueba determinada, puedo configurar mi propio SynchronizationContext.
Tenga en cuenta que este no es un método confiable para
Determine if code is running as part of a unit test
lo solicitado por OP, ya que el código podría estar ejecutándose dentro de un hilo, pero para ciertos escenarios, esta podría ser una buena solución (también: si ya estoy ejecutando desde un hilo en segundo plano, puede que no sea necesario para iniciar uno nuevo).fuente
Application.Current es nulo cuando se ejecuta bajo el probador de la unidad. Al menos para mi aplicación WPF que usa MS Unit tester. Es una prueba fácil de hacer si es necesario. Además, algo a tener en cuenta al usar Application.Current en su código.
fuente
He usado lo siguiente en VB en mi código para verificar si estamos en una prueba unitaria. específicamente, no quería que la prueba abriera Word
fuente
¿Qué tal usar la reflexión y algo como esto?
var underTest = Assembly.GetCallingAssembly ()! = typeof (MainForm) .Assembly;
El ensamblado de llamada estará donde están sus casos de prueba y simplemente sustituirá a MainForm por algún tipo que esté en su código que se está probando.
fuente
También hay una solución realmente simple cuando estás probando una clase ...
Simplemente dé a la clase que está probando una propiedad como esta:
Ahora su prueba unitaria puede establecer el booleano "thisIsUnitTest" en verdadero, por lo que en el código que desea omitir, agregue:
Es más fácil y rápido que inspeccionar los ensamblajes. Me recuerda a Ruby On Rails, donde mirarías para ver si estás en el entorno TEST.
fuente