2015-10-09 1 views
2

J'ai quelques problèmes avec le fait de railler une variable locale dans une méthode de ma classe.Modélisation d'une variable locale dans la méthode d'appel

Je tente de mocker ma classe Worker mais elle appelle une méthode qui renvoie une valeur nulle et ma variable de contexte devient null. De ce fait, je reçois une exception lorsque j'essaie d'obtenir la propriété Name.

Comment forcer CreateWorkerContext() pour renvoyer des valeurs fictives? Peut-il y avoir un moyen de se moquer d'une variable locale (context)?

Merci!

Mon code dira plus sur le problème:

namespace Moq 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var workerMock = new Mock<Worker>(); 
      workerMock.Object.GetContextName(); 
     } 
    } 

    public class Worker 
    { 
     public string GetContextName() 
     { 
      // something happens and context does not create (imitated situation) 
      WorkerContext context = CreateWorkerContext(); 

      // exception because _context is null 
      return context.Name; 
     } 

     private WorkerContext CreateWorkerContext() 
     { 
      // imitate that context is not created 
      return null; 
     } 
    } 

    public class WorkerContext 
    { 
     public string Name { get; set; } 
    } 
} 
+1

Vous devez extraire ou modifier 'WorkerContext CreateWorkerContext()' entièrement. Peut-être injecter un 'IWorkerContextFactory' dans le constructeur' Worker'. – CodeCaster

+0

1 pour l'usine. Ou rendre le 'IWorkerContex' injectable. – rbm

+0

Il n'y a donc aucun moyen de se moquer sans changer le code initial. Triste – yurart

Répondre

5

Quelques choses sont défendables ici.

Première, - mais cela est juste mon opinion - vous devriez éviter d'avoir un mock partiel (mock partiel = railler une classe abstraite qui ne met pas en œuvre une interface, et donc, maintient la mise en œuvre originale des méthodes qui weren pas moqué.). Le mieux serait d'avoir une interface IWorker que Worker mettrait en œuvre.

Deuxième - Je créerais des imitations strictes. se moque loose semblent comme un raccourci bien, mais souvent laisser vos méthodes et propriétés renvoient la valeur par défaut lorsque vous ne l'intention de (null dans votre cas)

Troisième - J'Injecter WorkerContext. Si vous ne pouvez pas injecter parce que vous devez venir avec paramétrisation .ctor arguments, puis injecter un WorkerContextFactory qui vous permettra de se moquer de la création et paramétrisation de vos WorkerContext

3

bibliothèques dynamiques comme des simulacres Moq sont, en général, pas de magie. They can only replace the behaviour that you yourself could replace with code.

Dans cet exemple particulier, Moq ne peut pas remplacer CreateWorkerContext car il s'agit d'une méthode privée.

Une option est de faire virtual:

public class Worker 
{ 
    public string GetContextName() 
    { 
     WorkerContext context = CreateWorkerContext(); 
     return context.Name; 
    } 

    public virtual WorkerContext CreateWorkerContext() 
    { 
     return new WorkerContext(); 
    } 
} 

Une autre option serait de remplacer la méthode CreateWorkerContext avec un Strategy:

public class Worker 
{ 
    private readonly IWorkerContextFactory factory; 

    public Worker(IWorkerContextFactory factory) 
    { 
     if (factory == null) 
      throw new ArgumentNullException(nameof(factory)); 

     this.factory = factory; 
    } 

    public string GetContextName() 
    { 
     WorkerContext context = this.factory.Create(); 
     return context.Name; 
    } 
} 

ces deux options permettrait Moq de simuler le choix comportement.