2010-06-18 21 views
2

J'ai écrit quelques tests pour le code .net qui appelle des appels à mon SQL Server. Il semble que l'utilisation de System.Transactions soit un excellent choix pour annuler toute modification de la base de données. Je suis conscient que certains puristes suggèrent que je pourrais vouloir se moquer de la base de données, mais je ne vais pas dans cette direction; ce n'est pas strictement un test unitaire.SQL Server et TransactionScope (avec MSDTC): sporadiquement impossible d'obtenir la connexion

Lorsque j'écris et exécute plusieurs tests, cela fonctionne exactement comme prévu. Je mets simplement le code pour initialiser et annuler les transactions .net dans les méthodes de test et de démontage des tests. Cela semblait être une excellente solution. Cependant, le problème que j'ai, c'est que lorsque j'essaie d'exécuter 100 de ces tests, beaucoup d'entre eux vont émettre une exception qu'ils ne pourraient pas se connecter au SQL Server même s'ils passent quand ils sont exécutés un par un. Pour ne rien arranger, les tables de ma base de données sont parfois verrouillées lorsque je lance mes tests. Je dois demander à mon administrateur de base de données de retirer manuellement les verrous.

Comme beaucoup d'entre vous le savez, l'utilisation de TransactionScope sur du code qui s'exécute sur un poste de travail de développement (comme lors de l'exécution de ce test) sur un serveur SQL fera utiliser l'infrastructure .net MSDTC.

Voici un exemple de code pour illustrer ce que je fais:

<TestInitialize()> Public Sub MyTestInitialize() 
    _scope = New System.Transactions.TransactionScope(_ 
     System.Transactions.TransactionScopeOption.Required, New TimeSpan(0, 2, 0)) 
End Sub 
<TestCleanup()> Public Sub MyTestCleanup() 
    _scope.Dispose() 
End Sub 

<TestMethod()> Public Sub CurrentProgramUser_Get_UserID() 
    Dim ProgramSessionId As String 
    Dim CurrentProgramUserId As Integer 
    Dim dSession As ProgramSession 
    CurrentDCMAUserId = Convert.ToInt32(_ 
    SqlHelper.ExecuteScalar(testDcmaConnString, System.Data.CommandType.Text, _ 
    "INSERT into Program_Users(UserName,FirstName,LastName) " & _ 
    "VALUES('GuitarPlayer','Bob','Marley')" & _ 
    "SELECT IDENT_CURRENT('Program_users') ") _ 
         ) 
    ProgramSessionId = session.getCurrentSession() 
    session.WriteUserParam("Program", ProgramSessionId, "USERID", CurrentProgramUserId.ToString(), testSource, testConnString) 

    Dim readValue As Integer 
    readValue = session.User.UserID 

    Assert.AreEqual(CurrentProgramUserId, readValue) 
End Sub 

Comme vous pouvez le voir, il n'y a rien ici particulièrement de fantaisie. J'ai juste une méthode de test qui va écrire des choses dans ma base de données que je veux que ma méthode trouve. Ceci est seulement un exemple; il y a beaucoup d'autres tests comme ça.

La logique de mes tests semble être saine. Qu'est-ce qui pourrait faire échouer non seulement mes tests, mais aussi bloquer sporadiquement les utilisateurs hors des tables?

+2

Le verrou peut être lié à des transactions non validées (ou non annulées en cas d'erreur). Assurez-vous que vous validez/rollback correctement –

Répondre

2

J'ai trouvé le problème. L'une des méthodes que je testais utilise un objet SqlDataReader. Apparemment, la méthode Close() doit être appelée avant que le SqlDataReader ne soit hors de portée afin de libérer la connexion, mais dans mon cas, je n'ai pas réussi à le faire.

L'ajout de mySqlDataReader.Close() à la fin de la méthode testée a permis de résoudre le problème. En outre, la méthode de test pour tester cette méthode particulière était pilotée par les données avec plus de 100 cas de test, ce qui explique comment j'aurais pu manquer de connexions.

+0

Quel est le code source correct, non? – Kiquenet

+0

Non, c'était en fait une autre méthode de test ... Le long et le court, c'est que les connexions ne sont pas forcément relâchées entre les tests. –