2008-12-08 23 views
13

Estoy creando una aplicación que administrará varias instancias de una utilidad externa, proporcionando datos y obteniendo resultados.Proceso de prueba. ¿Iniciar?

Pero como estoy escribiendo pruebas unitarias para la clase, me encontré con un problema.

¿Cómo probar que el método objetivo realmente inicia un proceso (establecido a través de una propiedad) cuando se llama?

que he intentado:

  • hacer que la clase ejecutar un proceso externo y luego utilizar GetProcessesByName para comprobar si se ha iniciado.
  • Utilice la redirección de salida, p. usando el signo más grande que para hacer eco de algo en un archivo y probar su existencia

Tengo ganas de emitir código y/o crear otro exe más para probar es exagerado.

Este es el método exacto:

public void Start() 
{ 
    if (!_isRunning) { 
     var startInfo = new ProcessStartInfo() { 
      CreateNoWindow = true, 
      UseShellExecute = true, 

      FileName = _cmdLine, 
      Arguments = _args 
     }; 

     _process = Process.Start(startInfo); 
     _isRunning = true; 

    } else { 
     throw new InvalidOperationException("Process already started"); 

    } 
} 

Quiero unidad de prueba de modo que si no se está ejecutando (_isRunning == false), un nuevo proceso debe ser generado.

Me siento perplejo, ¿hay alguna manera elegante de probar la unidad que realmente comienza un proceso externo?

Respuesta

10

Me acercaría a esto usando inyección de dependencia y usando una clase falsa o falsa. Tenga en cuenta que estoy usando el método de instancia para el inicio en lugar del método de la clase. En su código normal, puede usar el constructor predeterminado y creará un proceso para usted. Para probar, puede inyectar un proceso simulado o falso y simplemente verificar que se invoquen los métodos adecuados para su objeto simulado y nunca tener que iniciar un proceso en absoluto. Deberá ajustar esto para tener en cuenta las propiedades que he omitido. Ex. a continuación:!

public class UtilityManager 
{ 
     public Process UtilityProcess { get; private set; } 

     private bool _isRunning; 

     public UtilityManager() : this(null) {} 

     public UtilityManager(Process process) 
     { 
      this. UtilityProcess = process ?? new Process(); 
      this._isRunning = false; 
     } 

     public void Start() 
     { 
      if (!_isRunning) { 
      var startInfo = new ProcessStartInfo() { 
       CreateNoWindow = true, 
       UseShellExecute = true, 

       FileName = _cmdLine, 
       Arguments = _args 
      }; 

      this.UtilityProcess.Start(startInfo); 
      _isRunning = true; 

     } else { 
      throw new InvalidOperationException("Process already started"); 
     } 
} 

Código de ensayo ...

[TestMethod] 
public void StartTest() 
{ 
     Process proc = new FakeProcess(); // May need to use a wrapper class 
     UtilityManager manager = new UtilityManager(proc); 
     manager.CommandLine = "command"; 
     ... 

     manager.Start(); 


     Assert.IsTrue(proc.StartCalled); 
     Assert.IsNotNull(proc.StartInfo); 
     Assert.AreEqual("command", proc.StartInfo.FileName); 
     ... 
} 
+0

Niza ... Me pasa por alto la parte de separación startInfo ... tiene que conseguir mi cabeza alrededor de burlarse un poco más ... Gracias! – chakrit

+0

Puede cambiar 'utilityManager público(): this (null) {} UtilityManager público (Proceso de proceso)' a 'Public UtilityManager (Process process = null)' para código más corto. – Bomberlt

+0

@Bomberlt no si quiero que un constructor predeterminado esté disponible para ser utilizado por las herramientas que acceden a él a través de la reflexión. – tvanfosson

Cuestiones relacionadas