2012-04-13 11 views
6

Estoy usando MSTest para ejecutar algunas pruebas automatizadas contra una base de datos MySQL 5.5.19 a través del conector MySQL y utilizando EntityFramework 4.3.TransactionScope anidado falla en las pruebas

Estoy intentando usar TransactionScope en mi biblioteca de clase de acceso a base de datos para realizar una reversión cuando sea necesario. Además, en mi código de prueba deseo usar TransactionScope para volver a poner el DB en un estado conocido antes de cada prueba. Yo uso los métodos TestInitialize y TestCleanup para lograr esto. Los que se ven así:

[TestInitialize()] 
public void MyTestInitialize() 
{ 
    testTransScope = new TransactionScope(TransactionScopeOption.RequiresNew); 
} 

[TestCleanup()] 
public void MyTestCleanup() 
{ 
    Transaction.Current.Rollback(); 
    testTransScope.Dispose(); 
} 

Sobre la base de la construcción del objeto TransactionScope allí en la función de inicialización, creo que debería llegar a un nuevo ámbito de transacción (no hay un "ambiente" existente por lo que creo este ".RequiresNew" no es técnicamente importante aquí ya que ".Required" produciría el mismo resultado. Como no especifico un valor de tiempo de espera, me da el tiempo de espera predeterminado, que entiendo es de 60 segundos. . tiempo para mi prueba determinada para ejecutar

tengo una función llamada AddDessert(DessertBiz dessertBizObject) que parece, en parte, algo como esto:

using (var transScope = new TransactionScope(TransactionScopeOption.Required)) 
{ 
    try 
    { 
     // ... 
     context.Desserts.Add(dessert); 
     context.SaveChanges(); 
     var dessertId = dessert.Id; 
     DoOtherDessertStuff(dessertId, dessertBizObject); 
     transScope.Complete(); 
    } 
    catch (InvalidOperationException ex) 
    { 
     Console.WriteLine(ex.ToString()); 
    } 
} 

Y una de mis pruebas llama a esta función.

Como he especificado TransactionScopeOption.Required aquí, espero que utilice el ámbito de transacción "ambiente" creado por la función MyTestInitialize.

Mi prueba está dispuesto a realizar esta función DoOtherDessertStuff a fallar y lanzar una excepción, por lo que la llamada a transScope.Complete(); no sucede y el retroceso se produce automáticamente al salir del bloque using en la función AddDessert.

El problema que tengo es que ya que utiliza el ámbito de transacción ambiente creado en la función MyTestInitialize, mi prueba Assert llamadas no suceden porque la cancelación ámbito de transacción sucedió - al menos eso es lo que creo que está pasando. Verifiqué que Transaction.Current.TransactionInformation.Status es TransactionStatus.Aborted, así que estoy bastante seguro de que esto es lo que está sucediendo.

Grande, así que pensé que iba a cambiar mi método AddDesert para mirar exactamente como antes, excepto que lo haría anidar un ámbito de transacción en lugar de utilizar el ambiente, un poco de mi línea using ve ve así:

using (var transScope = new TransactionScope(TransactionScopeOption.RequiresNew)) 

La intención aquí era poder anidar estos ámbitos de transacción, permitir que se produzca la reversión en mi código de producción y, luego, seguir verificando mis Assert en mi código de prueba.

Pero lo que estoy encontrando es que me sale el siguiente error:

System.IO.IOException: No se puede leer los datos de la conexión de transporte: Un intento de conexión porque la parte conectada no respondió adecuadamente tras un período de tiempo o la conexión establecida falló porque el host conectado no respondió.

Ideas?

+0

fija por favor la StackTrace y el código donde pasa. – usr

Respuesta

0

Muy buena pregunta. Cuando hace referencia al contexto de datos dentro de su método de prueba después de la reversión, no estará disponible. Debes suprimir eso. No necesita especificar la opción requerida.Es la opción predeterminada.

Método de prueba:

[TestMethod()] 
    public void CreateTestCheckContextCorrectly() 
    { 
     MailJobController target = new MailJobController(); 

     target.AddDessert("dessert for Omer"); 
     //With suppress, even if you rollback ambient trans, suppress will ignore ambient trans. You need to reference new context, previous context from controller may be disposed. 
     using (var suppressscope = new TransactionScope(TransactionScopeOption.Suppress)) 
     { 
      var newdbcontextref = new DbEntities(); 

      int recordcount = newdbcontextref.StatusDefinitions.Where(x => x.Name == "dessert for Omer").Count(); 

      Assert.AreEqual(0, recordcount); 
     } 
    } 

método de control:

public void AddDessert(string dessert) 
    { 
     using (var transScope = new TransactionScope()) 
     { 
      try 
      { 
       // ... 
       StatusDefinition statusDefinition = new StatusDefinition() {Name = dessert}; 
       db.StatusDefinitions.AddObject(statusDefinition); 
       db.SaveChanges(); 
       Console.WriteLine("object id:"+statusDefinition.StatusDefinitionId); 
       throw new Exception("hee hee"); 
       transScope.Complete(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
     } 
    } 
Cuestiones relacionadas