2009-09-11 3 views
4

J'ai rencontré un problème lors de la configuration d'un test pour une méthode Equals sur un objet.Exceptions de RhinoMocks lors du tronquage Méthode Equals

L'objet en question est définie par cette interface:

public interface IHours { 
    ITimeOfDay OpenAt { get; set; } 
    ITimeOfDay CloseAt { get; set; } 
    DateTime ValidFrom { get; set; } 
    DateTime ValidTo { get; set; } 
    bool isCovered(DateTime time); 
} 

et il contient des références à ITimeOfDay définies comme:

public interface ITimeOfDay { 
    DateTime Time { get; set; } 
    int Hour { get; } 
    int Minute { get; } 
    int Second { get; } 
} 

Maintenant, je veux Egaux des Heures: IHours pour vérifier la OpenAt et CloseAt IHours. Pour mettre cela en place, j'essaie de sortir ces valeurs de propriété, et de retourner juste vrai et faux en fonction de ce que mon test particulier a besoin d'être.

[SetUp] 
    public virtual void SetUp() { 
     mocks = new MockRepository(); 

     defaultHours = getHours(); 
     otherHours = getHours(); 

    } 

    [TearDown] 
    public virtual void TearDown() { 
     mocks.ReplayAll(); 
     mocks.VerifyAll(); 
    } 

    [Test(Description = "Equals on two Hours should regard the fields")] 
    public void Equals_TwoValueEqualledObjects_Equal() { 
     var openAt = mocks.Stub<ITimeOfDay>(); 
     var closeAt = mocks.Stub<ITimeOfDay>(); 

     closeAt         //this is line 66, referenced in the error stacktrace 
      .Stub(o => o.Equals(null)) 
      .IgnoreArguments() 
      .Return(true); 

     openAt 
      .Stub(c => c.Equals(null)) 
      .IgnoreArguments() 
      .Return(true); 
     mocks.ReplayAll(); 

     defaultHours.OpenAt = openAt; 
     otherHours.OpenAt = openAt; 

     defaultHours.CloseAt = closeAt; 
     defaultHours.CloseAt = closeAt; 

     Assert.That(defaultHours, Is.EqualTo(otherHours)); 
     Assert.That(defaultHours.GetHashCode(), Is.EqualTo(otherHours.GetHashCode())); 
    } 

Mais je reçois cette erreur cryptique quand je le lance:

System.InvalidOperationException: Type 'System.Boolean' doesn't match the return type 'System.Collections.Generic.IList`1[NOIS.Model.Interfaces.IAircraft]' for method 'IAircraftType.get_Aircrafts();' 
at Rhino.Mocks.Expectations.AbstractExpectation.AssertTypesMatches(Object value) 
at Rhino.Mocks.Expectations.AbstractExpectation.set_ReturnValue(Object value) 
at Rhino.Mocks.Impl.MethodOptions`1.Return(T objToReturn) 
at Nois.Test.Model.Entities.HoursTest.Equals_TwoValueEqualledObjects_Equal() in HoursTest.cs: line 66 

L'interface IAircraftType est une partie du même espace, mais nulle part dans le test, l'interface ou une classe implémentant est-il fait référence. Je ne comprends pas pourquoi cela interfère. Il n'y a aucune référence à cela autant que je peux rassembler.

J'utilise - Rhino.Mocks v3.5.0.1337 - NUnit.Framework v2.5.0.8332

Quelqu'un a une idée?

+0

Ceci est un test assez compliqué - est-il possible de rendre le code complet disponible?Je vais passer à travers cela et voir si je peux reproduire votre erreur, mais ça va être difficile sans la source –

+0

Nevermind, voir ma réponse - c'est en fait un cas très intéressant. –

+0

Je ne peux pas fournir la source complète à tout, désolé. Je vais essayer de choisir autant que nécessaire et le mettre dans un projet distinct. Si cela produit encore l'exception étrange, je l'afficherai. – Tomas

Répondre

7

Ouais c'est compliqué - l'erreur est folle, cela n'a rien à voir avec IAircraft. Essentiellement le problème est que une interface n'est pas une classe et n'hérite donc pas de l'objet. En d'autres termes, closeAt n'a pas de méthode Equals à remplacer.

En fait, c'est probablement un peu un flub de langue que vous pouvez même appeler Equals() explicitement sur un objet cast vers une interface.

Deux façons de résoudre ce alors

  1. Ne pas se moquer de l'interface, la mise en œuvre se moquer mocks.Stub() - cela n'ont une égale méthode qui est virtuelle pour que votre code fonctionne.
  2. Encore mieux, ajoutez une méthode Equals à votre interface. Une fois que vous faites cela, vous serez en mesure de le remplacer et comme toutes les classes héritent de l'objet, vous n'aurez pas à l'implémenter explicitement (sauf si vous le souhaitez).

En d'autres termes

var intrface = MockRepository.GenerateStub<IInterface>(); 
intrface.Stub(x => x.Equals(null)).IgnoreArguments().Return(true); 

pauses lorsque

public interface IInterface { 
} 

mais fonctionne

public interface IInterface { 
    bool Equals(object obj); 
} 
+1

Aaaaaahhhh! Oooooohh! Bien sûr! (front smack!) – Tomas

+0

J'ai tweeté cela à Ayende, j'espère qu'il peut peser sur l'erreur carzy –

0

À moins que je me manque quelque chose, l'heure du jour devrait être un simple immuable objet. Je l'implémenterais donc comme une petite classe de valeur testée. Ensuite, vous pouvez utiliser la méthode réelle Equals.

+0

Ceci est vrai dans ce cas particulier. Je l'ai fait pendant un moment, mais ma curiosité foudroyante ne me laissait pas en rester là. Pour lequel je suis maintenant heureux, car la réponse de George ci-dessus a fait un terrible vendredi plusieurs fois mieux. – Tomas

Questions connexes