web-dev-qa-db-fra.com

Mock propriété statique avec moq

Je suis assez nouveau pour utiliser moq . Je suis en train de créer un scénario de test unitaire pour HttpModule et tout fonctionne correctement jusqu'à ce que je clique sur une propriété static comme suit 

this.applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty;

Je ne sais pas comment créer des exemples pour static classe et propriété comme HttpRuntime.AppDomainAppVirtualPath. Les context, request et response ont été bien moqués avec l'exemple de code que je reçois de moq. J'apprécierai si quelqu'un peut m'aider à ce sujet.

41
jyothish george

Moq ne peut pas simuler de membres statiques.

En tant que solution, vous pouvez créer une classe wrapper (Adapter Pattern) contenant la propriété static et simuler ses membres.
Par exemple:

public class HttpRuntimeWrapper
{
    public virtual string AppDomainAppVirtualPath 
    { 
        get
        { 
            return HttpRuntime.AppDomainAppVirtualPath; 
        }
    }
}

Dans le code de production, vous pouvez accéder à cette classe au lieu de HttpRuntime et simuler cette propriété:

[Test]
public void AppDomainAppVirtualPathTest()
{
    var mock = new Moq.Mock<HttpRuntimeWrapper>();
    mock.Setup(fake => fake.AppDomainAppVirtualPath).Returns("FakedPath");

    Assert.AreEqual("FakedPath", mock.Object.AppDomainAppVirtualPath);
}

Une autre solution consiste à utiliser le cadre d’isolation (sous la forme Typemock Isolator ) dans lequel vous pouvez simuler des classes et des membres statiques.
Par exemple:

Isolate.WhenCalled(() => HttpRuntime.AppDomainAppVirtualPath)
       .WillReturn("FakedPath");

Disclaimer - Je travaille chez Typemock

60
Elisha

Vous ne pouvez pas utiliser les méthodes statiques Moq avec Moq.

Ce n'est pas une mauvaise chose en réalité: les méthodes et les classes statiques ont leur place, mais pour la logique, elles rendent les tests unitaires difficiles. Naturellement, vous les rencontrez lorsque vous utilisez d'autres bibliothèques. Pour résoudre ce problème, vous devez écrire un adaptateur (wrapper) autour du code statique et fournir une interface. Par exemple:

// Your static class - hard to mock
class StaticClass
{
   public static int ReturnOne() 
   {
       return 1;
   }
}

// Interface that you'll use for a wrapper
interface IStatic
{
    int ReturnOne();
}

Remarque, j'ai omis la classe concrète qui utilise IStatic pour le code de production. Allit serait une classe qui utilise IStatic et votre code de production utiliserait cette classe plutôt que StaticClass ci-dessus.

Puis avec Moq:

var staticMock = new Mock<IStatic>();
staticMock.Setup(s => s.ReturnOne()).Returns(2);
11
Finglas

Comme mentionné dans les réponses précédentes, vous ne pouvez pas utiliser MoQ sur des méthodes statiques. Si vous en avez le besoin, votre meilleure idée consiste à créer un wrapper autour de la classe statique.

Cependant, quelque chose que j'ai découvert récemment est le projet Moles . De la page d'accueil; "Moles permet de remplacer n'importe quelle méthode .NET par un délégué. Moles supporte les méthodes statiques ou non virtuelles." Cela pourrait être utile pour votre situation actuelle.

3
Kirschstein

La meilleure solution que j’ai trouvée jusqu’à présent est celle de Telerik JustMock - malheureusement, seule la version payante permet de se moquer de la statique. 

Bien que l'idée d'encapsuler la statique soit bonne, vous ne pouvez pas toujours le faire. Si vous souhaitez tester du code qui utilise déjà des classes statiques, il n'est pas toujours possible de basculer et d'utiliser un wrapper. Dans ce cas, JustMock semble une solution raisonnable et je vais probablement l’utiliser dans un avenir proche.

2
Ian

Vous pouvez utiliser Microsoft Fakes pour cela. Cela résoudra définitivement le problème. Reportez-vous à https://msdn.Microsoft.com/en-us/library/hh549175.aspx

1
Sujith

Utiliser Microsoft Fakes comme suggéré par @Sujith est une solution viable. Voici comment vous le faites réellement:

  • Trouvez System.Web dans votre référence de votre projet test et faites un clic droit.
  • Choisissez "Ajouter". Ceci ajoute la référence System.Web.4.0.0.0.Fakes
  • Utilisez le code suivant:

    using (Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create ()) { System.Web.Fakes.ShimHttpRuntime.AppDomainAppVirtualPathGet = () => "/"; // Faites ce qui est nécessaire pour le faux AppDomainAppVirtualPath }

0
Jack Miller