2012-07-04 14 views
5

necesito para probar pieza de códigoprueba Unidad IObservable <T> con ObserveOnDispatcher

 var watcher = new FakeIFileSystemWatcher(); 
     watcher.FilesToBeImported 
      .ObserveOnDispatcher() 
      .Subscribe(list.Add); 

así que creé esta pequeña prueba de la unidad, pero no puedo hacerlo pasar list.Count causa es siempre 0

[Test] 
    public void Foo() 
    { 
     var list = new List<string>(); 

     var watcher = new FakeIFileSystemWatcher(); 
     watcher.FilesToBeImported 
      .ObserveOnDispatcher() 
      .Subscribe(list.Add); 

     Task task = Task.Factory.StartNew(() => 
     {     
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
     }, TaskCreationOptions.LongRunning); 
     Task.WaitAll(task); 

     Assert.AreEqual(3, list.Count); 
    } 

Si comento a cabo el método

  .ObserveOnDispatcher() 

pasar, pero ¿cómo puedo conseguir que funcione también con Observar OnDispatcher()?

+0

¿Cuál es el valor de 'list.Count 'en el fracaso? –

+0

Lo resolví usando la clase DispatcherUtil que encontré aquí http://stackoverflow.com/questions/1106881/using-the-wpf-dispatcher-in-unit-tests – jitidea

+0

Solo quiero señalar que al tener concurrencia (implícita o explícito) en sus pruebas de unidad, realmente está limitado en lo que puede hacer. Aquí tiene tanto tareas como un despachador que no ha proporcionado 'costuras' en las que puede sustituirlas por un doble de prueba (simulacro/stub). Del mismo modo que (supongo) usted inyecta una implementación real de IFileSystemWatcher en su código de producto, usted inyectaría un ProgamaProveedor que le dio concurrencia real en los programadores de prueba pero prueba en sus pruebas unitarias. Pruebas unitarias mucho más rápidas, más fáciles de probar otras cosas como tiempos de espera, etc. –

Respuesta

1

He resuelto utilizando la clase DispatcherUtil que encontré aquí Using the WPF Dispatcher in unit tests

ahora mi código es el siguiente

[Test] 
    public void Foo() 
    { 
     var list = new List<string>(); 

     var watcher = new FakeIFileSystemWatcher(); 
     watcher.FilesToBeImported 
      .ObserveOnDispatcher() 
      .Subscribe(list.Add); 

     Task task = Task.Factory.StartNew(() => 
     { 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
     }, TaskCreationOptions.LongRunning); 
     Task.WaitAll(task); 
     DispatcherUtil.DoEvents(); 
     Assert.AreEqual(4, list.Count); 
    } 

y funciona como un encanto

5

Si usa ObserveOnDispatcher crea una dependencia al "despachador", lo que significa que necesita una ventana y un bucle de mensajes. Para evitar este problema en una prueba unitaria, puede usar el método ObserveOn que usa un programador y luego usar la inyección de dependencia para inyectar el programador correcto. Para las pruebas unitarias puede usar Scheduler.Immediate y para la aplicación real puede usar DispatcherScheduler.Instance. Observe que también existe un TestScheduler que es realmente útil para ejecutar pruebas unitarias en tiempo virtual.

+0

Gracias por su respuesta. esta línea de código watcher.FilesToBeImported.ObserveOnDispatcher(). Suscribir (list.Add); está en mi sistema bajo prueba, así que no puedo cambiarlo solo para la prueba – jitidea

+3

@ scott4dev: Mi punto es que a veces tiene que modificar su sistema bajo prueba para que sea comprobable por unidad. P.ej. si accede a una base de datos, debe crear una interfaz para la base de datos que le permita acceder al acceso a la base de datos, etc. Su solución lo evitará, por supuesto. –

+0

tiene razón, a veces tiene que modificar su sistema bajo prueba para que sea comprobable por unidad, pero en mi opinión, este no es el caso. Prefiero usar DispatcherUtil.DoEvents(); en mis pruebas y dejar mi SUT en el estado original – jitidea

0

Usted puede tratar de invocar el método como esto:

var dispatcher = Application.Current != null ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher; 

dispatcher.Invoke((Action)(() => YourMethodToTest());