- No está probando métodos (privados o públicos) - está verificando el comportamiento de su clase.Y si no ha verificado algún comportamiento, entonces no puede decir que se implementó. Hay varias maneras en que se puede invocar este comportamiento: interfaz pública de su clase o algún evento en dependencia. Además, no es necesario que la invocación de comportamiento cambie algo alcanzado por la interfaz pública, las interacciones con las dependencias también importan.
- Vea el siguiente ejemplo: muestra cómo probar dicho comportamiento "oculto".
- Vea el ejemplo a continuación: muestra cómo dividir responsabilidades, inyectar dependencias y simularlas.
En realidad, su clase tiene demasiadas responsabilidades, una está programando una tarea y otra está ejecutando algunas acciones. Intenta dividir tu clase en dos clases separadas con single responsibilities.
Así, la programación va a planificador :) API de programador podría ser como:
public interface IScheduler
{
event EventHandler<SchedulerEventArgs> Alarm;
void Start();
void Stop();
}
Olvídate de planificador por ahora. Regrese e implemente su segunda clase, que mostrará algunas advertencias. Vayamos a la primera prueba (con Moq): aplicación
[Test]
public void ShouldStopDisplayingWarningsWhenTimeIsOut()
{
Mock<IDisplay> display = new Mock<IDisplay>();
Mock<IScheduler> scheduler = new Mock<IScheduler>();
Foo foo = new Foo("Bar", scheduler.Object, display.Object);
scheduler.Raise(s => s.Alarm += null, new SchedulerEventArgs(0));
display.Verify(d => d.Execute("Bar", WarningState.Ending, null));
scheduler.Verify(s => s.Stop());
}
Comentario:
public class Foo
{
private readonly IScheduler _scheduler;
private readonly IDisplay _display;
private readonly string _name;
public Foo(string name, IScheduler scheduler, IDisplay display)
{
_name = name;
_display = display;
_scheduler = scheduler;
_scheduler.Alarm += Scheduler_Alarm;
_scheduler.Start();
}
private void Scheduler_Alarm(object sender, SchedulerEventArgs e)
{
_display.Execute(_name, WarningState.Ending, null);
_scheduler.Stop();
}
}
pasa la prueba. Escriba otro:
[Test]
public void ShouldNotStopDisplayingWarningsWhenTimeRemains()
{
Mock<IDisplay> display = new Mock<IDisplay>(MockBehavior.Strict);
Mock<IScheduler> scheduler = new Mock<IScheduler>(MockBehavior.Strict);
scheduler.Setup(s => s.Start());
Foo foo = new Foo("Bar", scheduler.Object, display.Object);
scheduler.Raise(s => s.Alarm += null, new SchedulerEventArgs(1));
}
Error de prueba. Ah, es necesario condición para el tiempo restante:
private void Scheduler_Alarm(object sender, SchedulerEventArgs e)
{
if (e.RemainingTime > 0)
return;
_display.Execute(_name, WarningState.Ending, null);
_scheduler.Stop();
}
Puede seguir las pruebas de escritura para su clase, la cual responsable de atender las alertas planificador y ejecutar algunas advertencias en la pantalla. Cuando termine, puede escribir la implementación para su interfaz IScheduler
. No importa cómo implementará la programación, a través de System.Windows.Forms.Timer o a través de System.ThreadingTimer, o de alguna otra manera.
¿Qué comportamiento desea verificar? –
¿El método real en sí tiene alguna dependencia en el tiempo? Su prueba de unidad debe probar la funcionalidad del método; el hecho de que se llame con regularidad no debe alterar el hecho de que desea probar que el método funciona. Diría que definitivamente no hay necesidad de burlarse de un temporizador a menos que el éxito del método dependa del tiempo. El acceso de un método no debería importar cuando se trata de pruebas; es una parte funcional de tu programa. – dash
+1 porque estaba escribiendo exactamente la misma pregunta para las pruebas de campos privados, me ganaste a tiempo – HatSoft