2010-06-01 6 views
11

En C# Je peux tester cette ...Y a-t-il un moyen de savoir dans VB.NET si un gestionnaire a été enregistré pour un événement?

public event EventHandler Trigger; 
protected void OnTrigger(EventArgs e) 
{ 
    if (Trigger != null) 
     Trigger(this, e); 
} 

Est-il possible de le faire en VB.NET? Test pour null je veux dire?

PLUS D'INFO

j'oublié de mentionner. J'ai des cours écrits en C# mais j'écris mes tests unitaires en VB.NET.

J'essaie ceci dans le test unitaire ...

If myObject.Trigger IsNot Nothing Then 
    ''#do something 
End If 

Cela provoque une erreur de compilation qui dit ... « Trigger Event public est un événement et ne peut pas être appelée directement. Utilisez le RaiseEvent déclaration pour élever un événement. "

Seth

+0

PS ... mon point est que je DON "T veulent déclencher l'événement. En fait, je veux vérifier la nullité parce que est ce que je suis pour les tests unitaires. Seth –

+0

J'ai répondu à la question ci-dessous Cependant, je suggérerais aussi que ce que vous devriez tester est qu'une tentative a été faite pour enregistrer un gestionnaire d'événement, pas qu'il ait été réellement enregistré (puisque cela testerait la fonctionnalité CLR qui est déjà bien testée.) Plus spécifiquement, considérons en utilisant un [objet simulé] (http://martinfowler.com/articles/mocksArentStubs.html) qui est rendu plus facile avec des frameworks comme [Rhino.Mocks] (http://www.ayende.com/projects/rhino-mocks). aspx), [Moq] (http://code.google.com/p/moq/), ou [Isolateur TypeMock] (http://site.typemock.com/) – hemp

Répondre

7

Il existe une discussion intéressante à la question 1129517 sur la façon de faire cette chose en C#. Puisque la classe qui contient l'événement a été écrite en C#, la sémantique du délégué s'applique, et ces techniques devraient fonctionner pour vous. Cependant, vous devrez traduire la source vers VB.NET pour votre test unitaire.

Compte tenu de la classe suivante dans un assemblage C#:

public class Triggerific 
{ 
    public event EventHandler Trigger; 

    private static void OnTriggerTriggered(object sender, EventArgs e) 
    { 
     Console.WriteLine("Triggered!"); 
    } 

    public void AddTrigger() 
    { 
     Trigger += OnTriggerTriggered; 
    } 
} 

Voici un code VB.NET qui correctement déterminer si un gestionnaire a été enregistré pour l'événement déclencheur:

<TestMethod()> _ 
Public Sub TriggerTest() 
    Dim cut As New Triggerific 
    cut.AddTrigger() 

    Assert.IsNotNull(GetEventHandler(cut, "Trigger")) 
End Sub 

Private Shared Function GetEventHandler(ByVal classInstance As Object, ByVal eventName As String) As EventHandler 
    Dim classType As Type = classInstance.[GetType]() 
    Dim eventField As FieldInfo = classType.GetField(eventName, BindingFlags.GetField Or BindingFlags.NonPublic Or BindingFlags.Instance) 

    Dim eventDelegate As EventHandler = DirectCast(eventField.GetValue(classInstance), EventHandler) 

    ' eventDelegate will be null/Nothing if no listeners are attached to the event 
    Return eventDelegate 
End Function 
+0

chanvre ... merci pour votre réponse et votre recommandation que ce est mieux adapté à moquer. Je l'ai sur mon agenda pour apprendre les rhinocéros. Seth –

+0

Pas génial. Ça ne marche pas. L'événement n'est pas un champ dans VB.NET. Cela fonctionne uniquement comme méthode de test VB.NET pour le code C#, auquel cas il est inutile ... Mais cela fonctionne si vous faites eventName + "Event" pour le nom du champ, car le compilateur VB crée automatiquement un champ pour chaque événement . –

+1

@Quandary l'OP a déclaré: "J'ai des cours écrits en C# mais j'écris mes tests unitaires en VB.NET." Quel est le problème que cette réponse a résolu (et n'est évidemment pas inutile.) Il serait plus utile de poser une nouvelle question sur la façon de faire cela pour les classes VB.NET et d'y répondre en conséquence au lieu de revendiquer la réponse travail ", car il le fait. – hemp

11

Oui. null est appelé "Nothing" dans Visual Basic.

If Trigger IsNot Nothing Then 

Mise à jour

La réponse ci-dessus décrit comment vérifier quelque chose pour null dans VB .NET. Malheureusement, les événements sont gérés par le compilateur VB.NET.

Pour cette définition de l'événement:

Public Event Trigger as EventHandler 

Vous utilisez ce code pour vérifier les abonnements

If TriggerEvent Is Nothing 

Remarquez comment VB.Net ajouté un champ avec le suffixe Event pour représenter le délégué. Avoir un look here for an explanation.

+1

+1, mais ne devrait pas être sacré ?;) Je veux dire viens! – kenny

+0

Merci pour votre réponse. Si vous regardez ma question, vous verrez que Trigger IsNot Nothing provoque une erreur de compilation dans vb.net J'ai oublié de mentionner cela dans ma question et vous avez répondu si rapidement que vous avez répondu avant de mettre à jour la question. Bottom line ... est votre code provoque une erreur de compilation. Seth –

+1

@Seth Spearman: Faites-le à la place: Si TriggerEvent IsNot Nothing –

8

Tout d'abord, il y a un problème avec votre code C#. Il faut lire comme ceci pour réduire la probabilité d'une condition de course sur la suppression du dernier gestionnaire dans un thread séparé juste au mauvais moment (indice pourquoi cela fonctionne: les délégués mulit-cast sont immuables):

public event EventHandler Trigger; 
protected void OnTrigger(EventArgs e) 
{ 
    var temp = Trigger; 
    if (temp != null) 
     temp(this, e); 
} 

En second lieu , il n'y a pas besoin de ce code du tout dans VB.Net. VB gère les événements un peu différemment, de sorte que vous ne devriez pas vérifier du tout si des gestionnaires sont enregistrés. Il est sûr et préféré de simplement augmenter l'événement:

Public Event Trigger As EventHandler 
Friend Sub OnTrigger(ByVal e As EventArgs) 
    RaiseEvent Trigger(Me, e) 
End Sub 
+1

Joel ... merci pour votre réponse. Je vais mettre à jour mon code. S'il vous plaît voir la mise à jour à ma question (Ceci est mon premier projet C# que j'utilise pour apprendre). Dans mon cas, je suis en train d'écrire un test unitaire et le test vérifie que le gestionnaire s'est inscrit à l'événement. Mais je suppose de votre réponse il n'y a aucun moyen de le faire dans vb.net. –

1

Vous ne devriez pas avoir un test d'unité pour vérifier si un gestionnaire est enregistré. Comment sauriez-vous si c'était le gestionnaire correct, ou si c'était le gestionnaire correct mais se comportait incorrectement?

Quel est le but de votre test?

+0

John, Merci pour votre réponse. C'est bien pris. Je travaille sur un projet "d'apprentissage" et je m'enseigne à la fois sur le C# et les tests unitaires. Je suppose que je prends l'approche d'utiliser le test unitaire pour définir votre API. J'ai donc une méthode dans ma classe sous test appel AddTrigger. Il va ajouter un objet dans cette collection et en même temps enregistrer un déclencheur dans cet objet. Je suis vraiment en difficulté avec quoi tester et quoi ne pas tester. Je réalise qu'il n'y a aucun intérêt à tester .NET ou toute autre bibliothèque externe. Mais là encore ... le setup/teardown ne définit qu'un seul triggerd. –

+0

Alors ... suite ... J'ai deux méthodes de test ... AddTrigger_TriggerNotExists_TriggerAdded() ... AddTrigger_TriggerNotExists_EventRegistered() ... Test du premier est simple ... vérifie juste qu'un élément a été ajouté à la collection. Il semblait s'assurer que le code .. quel que soit ...vérifierait que l'événement déclencheur a été enregistré. Mais peut-être pas. Seth –

4

Je crois la syntaxe que j'utilise pour cela dans VB.Net est:

Public Event Trigger As EventHandler 


Friend Sub OnTrigger(ByVal e As EventArgs) 
    If TriggerEvent IsNot Nothing Then 
     RaiseEvent Trigger(Me, e) 
    End If 
End Sub 

Même si triggerEvent-t n'a pas l'air d'être déclaré que le compilateur le comprendra. Plus proche émule la syntaxe C#. Aussi j'ai lu quelque part que le code avec ce contrôle asserigned de gestionnaire court fater, mais je ne peux pas pointer vers cela pour le moment, ainsi vous pouvez prendre ou laisser cela.

Je pense que c'est la sytax, de toute façon. S'il vous plaît ne me tirez pas si ce n'est pas tout à fait correct!

+0

Voici une explication de ceci. Le compilateur VB génère automatiquement un membre caché privé pour la déclaration d'événement: http://jelle.druyts.net/2003/05/09/BehindTheScenesOfEventsInVBNET.aspx – Technobabble

0

Il existe une "fonctionnalité" intéressante de langage dans VB .NET. Une variable membre est créée pour les événements qui exposent le délégué:

Public Event MyEvent As EventHandler 
Public Sub Test() 

    Dim test = MyEventEvent 
    Dim invokers = test.GetInvocationList() 

End Sub 

Vous pouvez réellement obtenir la liste d'invocation de cette manière.

Questions connexes