2010-11-12 3 views
0

J'ai une méthode simple dans une classe qui est responsable d'enregistrer un FileSystemWatcher donné un certain chemin dans appconfig.xml:Comment tester une méthode déléguée

public void ListenPath(string path){ 
    //path validation code 
    //... 

    FileSystemWatcher objFileWatcher = new FileSystemWatcher(); 
     objFileWatcher.Path = path; 
     objFileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite 
     | NotifyFilters.FileName | NotifyFilters.DirectoryName; 
     objFileWatcher.Filter = "*.txt"; 
     objFileWatcher.Created += new FileSystemEventHandler(ProcessInput); 
     objFileWatcher.EnableRaisingEvents = true; 
} 

Dans mon test unitaire je dois affirmer:

1) Donner un mauvais chemin ou nul, il devrait soulever une PathNotFoundException

2) Cette méthode ProcessInput a été correctement enregistrée pour écouter « chemin » lorsque les fichiers sont créés.

Comment puis-je effectuer le test unitaire pour l'article 2?

merci beaucoup

+0

Eh bien en fait je pense que je pourrais écrire un test qui crée un pool de fichiers lorsque la méthode est déclenché. Ensuite, dans le test unitaire, créez un fichier en dir et voyez si le fichier ajouté correspond au fichier dans le pool ... – Robert

Répondre

1

L'enregistrement d'un rappel sur un événement consiste simplement à renseigner une variable. C'est plus ou moins l'ajout d'un rappel à une liste de rappels. Je ne valide généralement pas les choses accessoires comme la population d'une liste, à moins que la population de données soit le point entier de la classe (comme si la classe représentait une structure de données personnalisée).

Vous pouvez à la place valider que ProcessInput est appelée lorsque vous modifiez le fichier spécifié. Quelques manières de procéder à ce sujet:

  • Les effets secondaires du test de ProcessInput, par ex. il a rempli une autre structure ou propriété dans votre programme
  • Séparer la méthode ProcessInput dans une autre classe ou interface. Prenez une référence à ce type en tant qu'argument à ListPath ou au constructeur de la classe. Puis railler ce type

exemple d'objet Mock:

public interface IInputProcessor 
{ 
    void ProcessInput(Object sender, FileSystemEventArgs e); 
} 

public class ClassUnderTest 
{ 
    public ClassUnderTest(IInputProcessor inputProcessor) 
    { 
     this.inputProcessor = inputProcessor; 
    } 

    public void ListenPath(string path){ 
     // Your existing code ... 
     objFileWatcher.Created += 
      new FileSystemEventHandler(inputProcessor.ProcessInput); 
     // ... 
    } 

    private IInputProcessor inputProcessor; 
} 

public class MockInputParser : IInputProcessor 
{ 
    public MockInputParser() 
    { 
     this.Calls = new List<ProcessInputCall>(); 
    } 

    public void ProcessInput(Object sender, FileSystemEventArgs args) 
    { 
     Calls.Add(new ProcessInputCall() { Sender = sender, Args = args }); 
    } 

    public List<ProcessInputCall> Calls { get; set; } 
} 

public class ProcessInputCall 
{ 
    public Object Sender; 
    public FileSystemEventArgs Args; 
} 

[Test] 
public void Test() 
{ 
    const string somePath = "SomePath.txt"; 
    var mockInputParser = new MockInputParser(); 
    var classUnderTest = new ClassUnderTest(mockInputParser); 
    classUnderTest.ListenPath(somePath); 
    // Todo: Write to file at "somePath" 
    Assert.AreEqual(1, mockInputParser.Calls.Count); 
    // Todo: Assert other args 
} 
0

Si le FileSystemWatcher est quelque chose que vous avez accès, vous pouvez le configurer de sorte que vous pouvez se moquer de la mise à feu de l'événement. Created Mais je soupçonne que ce n'est pas le cas, ce qui veut dire que vous en arrivez au point où le vrai «test unitaire» n'est pas très facile.

Vous pouvez essayer d'utiliser un isolateur comme TypeMock ou peut-être des Moles pour simuler le déclenchement de l'événement Created. Mais la chose la plus simple pourrait être d'écrire un test qui crée un fichier sur le chemin donné, et de s'assurer que la méthode ProcessInput est appelée quand cela arrive.

Parce que vous n'avez pas montré la définition ou tout autre code autour de ProcessInput lui-même, je ne connais pas la meilleure façon de s'assurer qu'il a été appelé.

0

Vous pouvez diviser votre méthode en deux: la première méthode instancie simplement, configure et renvoie une instance de FileSystemWatcher. Vous pouvez ensuite facilement tester sur l'objet résultat renvoyé. Une seconde méthode pourrait prendre comme argument et simplement permettre des événements croissants sur elle.

Questions connexes