2009-11-02 5 views
3

J'ai un Singleton qui est accessible dans ma classe via une propriété statique comme ceci: OtherClassNotBeingTested.Instance.SomeInstanceMethod()Rhino Mocks - Stub Singleton

Je voudrais tester ma classe en faisant un de ces objets. Existe-t-il un moyen pour RhinoMocks de renvoyer un stub lorsque le getter de la propriété statique Instance est appelé?

Pour être plus clair, voici le code de la propriété de l'instance:

/// <summary> 
    /// Make a property to allow the OtherClassNotBeingTested class 
    /// to be a singleton 
    /// </summary> 
    public static OtherClassNotBeingTested Instance 
    { 
     get 
     { 
      // Check that the instance is null 
      // NOTE: COMMENTS BELOW HAVE SHOWN THIS TO BE BAD CODE. DO NOT COPY 
      if (mInstance == null) 
      { 
       // Lock the object 
       lock (mSyncRoot) 
       { 
        // Check to make sure its null 
        if (mInstance == null) 
        { 
         mInstance = new OtherClassNotBeingTested(); 
        } 
       } 
      } 

      // Return the non-null instance of Singleton 
      return mInstance; 
     } 
    } 

Mise à jour: Voici comment j'ai fini par fixer:

class ClassBeingTested 
{ 
    public ClassBeingTested(IGuiInterface iGui):this(iGui, Control.Instance) 
    { 

    } 

    public ClassBeingTested(IGuiInterface iGui, IControl control) 
    { 
     mControl = control; 

     //Real Constructor here 
    } 
} 

Mes tests unitaires appellent le deuxième constructeur. Le code actuel appelle le premier constructeur. Le code de la classe utilise le champ local mControl au lieu du singleton. (Je pense que cela s'appelle l'injection de dépendance.)

J'ai également refaçonné le Singleton selon La suggestion de Tony le Pony.

Répondre

4

J'espère que votre variable mInstance est déclarée volatile, sinon votre implémentation DCL est cassée. Sérieusement, avez-vous vraiment besoin de ce niveau de paresse? Je recommande personnellement certains des simpler patterns available. Cependant, quand il s'agit de moquer - non, vous ne pouvez pas simuler des appels statiques avec RhinoMocks. Il y a quelques outils disponibles qui permettent cela, tels que Typemock, mais personnellement je refactoriser l'application pour être plus testable en premier lieu.

Une autre option consiste à avoir un singleton "tricheur" dans lequel vous pouvez définir la valeur de la propriété singleton dans votre scénario de test. Si vous faites en sorte que la propriété renvoie une interface au lieu de la classe singleton elle-même, vous pouvez remplacer le singleton réel par un simulacre.

+0

Cette construction est copiée et collée. Je vais le changer pour suivre le modèle dans votre lien. Je pense que je vais avoir une variable dans la classe que le singleton va assigner. De cette façon, je peux me moquer de ça. – Vaccano

+3

Pour ma part, bienvenue à notre Poney Overlord. –

+0

La réponse de Tony le Poney est correcte. Je voudrais ajouter que les problèmes de testabilité sont l'une des raisons pour lesquelles le modèle de Singleton est tombé en disgrâce. Vous pouvez envisager une structure de conteneur DI/IoC (Dépendance Injection/Inversion de Contrôle) telle que [Unity] (http://www.codeplex.com/unity) ou [StructureMap] (http: //structuremap.sourceforge. net/Default.htm) - ceux-ci peuvent créer Plain Old Objects avec des durées de vie semblables à celles de Singleton. – TrueWill

4

En dépit d'autres rumeurs que vous pouvez moquez singletons, voir ma réponse à:

How to Mock a Static Singleton?

Dans ce cas, il est encore plus simple, parce qu'il n'y a pas de constructeur statique. Si votre singleton implémente déjà une interface, il n'y aurait pas besoin de changer votre code de production.

Questions connexes