2010-09-08 29 views
12

I a ajouté une interface covariante à notre projet:échec de construction dans le projet de test unitaire avec accesseurs d'un projet contenant les types covariants

interface IView 
{ 
} 

interface IPresenter<out TView> where TView : IView 
{ 
    TView View { get; } 
} 

J'ai créé certaines classes, la mise en œuvre de ces interfaces:

class TestView : IView 
{ 
} 

class TestPresenter : IPresenter<TestView> 
{ 
    public TestView View 
    { 
    get { return something; } 
    } 

    private void DoSomething() 
    { 
    } 
} 

Et Je peux l'employer sans problèmes:

IPresenter<IView> presenter = new TestPresenter(); 

Ainsi tout semble juste, donc je suppose mon c l'utilisation de l'ovariance est correcte. Malheureusement, nos projets de tests unitaires contiennent des accesseurs privés de certains types situés dans le même projet comme l'interface covariant, ce qui provoque un échec de construction.

Could not load type 'GenericInheritanceTest.IPresenter_Impl`1' from assembly 'GenericInheritanceTest_Accessor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because it declares a covariant or contravariant type parameter and is not an interface or delegate.

Quel est exactement le problème ici? Y a-t-il un échec dans ma mise en œuvre, resp. Comment régler ceci? Ne peut pas être, que nous devons éviter les accesseurs dès que nous utilisons des types covariants ??? Est-il possible d'empêcher la création d'accesseurs pour certains types pour résoudre ce problème?

+0

Vous devriez éviter les accesseurs privés en général - ils provoquent un couplage trop étroit entre les tests et le code de production. – Grzenio

+0

Oui merci, mais j'ai ici un projet déjà existant avec 120k loc et un bon usage d'accesseurs privés, donc ce ne sera pas juste un bout du doigt pour le retravailler. – Enyra

Répondre

12

Ceci est un bogue dans Visual Studio 2010. Il a été signalé à Microsoft Connect mais a été fermé et ne sera apparemment pas corrigé. Selon un article de Bruce Taimana, le développement de the private accessor feature a été arrêté et pourrait être supprimé dans les futures versions de Visual Studio. Les alternatives possibles énumérées sont:

  1. Use the Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject class to assist in accessing internal and private APIs in your code. This is found in the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll assembly.

  2. Create a reflection framework that would be able to reflect off your code to access internal or private APIs.

  3. If the code you are trying to access is internal, you may be able to access your APIs using the InternalsVisibleToAttribute so your test code can have access to the internal APIs.

+3

Une réponse tardive mais merci :) Oui, les accesseurs privés sont obsolètes, en attendant nous avons supprimé tous les accesseurs privés dans notre projet. À partir de votre liste de solutions, je préfère le point 4. Améliorer la testabilité avec une bonne structure d'objet (IoC) :) – Enyra

0

Je luttais avec cette erreur et j'ai également eu une erreur: Le "BuildShadowTask" a échoué de façon inattendue. La seule façon de se débarrasser de l'erreur lorsque j'ai essayé de la résoudre ici est de supprimer le mot-clé out des génériques, c'est-à-dire une interface covariante.

En fait, j'ai eu cette erreur lorsque ReSharper m'a suggéré que le paramètre de type pourrait être Covariant:

private delegate TResult Action<TResult>(); 

Changé à:

private delegate TResult Action<out TResult>(); 

Malheureusement, je devais changer à nouveau et la désactivation de la Avertissement de resharper dans un commentaire:

// ReSharper disable once TypeParameterCanBeVariant 
private delegate TResult Action<TResult>(); 

Une stratégie peut donc être de saisir ch pour:

"<out" 

dans un projet et de supprimer le mot-clé, juste pour le compiler. Pas très élégant, mais pas très élégant par Microsoft non plus, parce que cela a été rapporté il ya cinq ans par l'intermédiaire de Microsoft Connect et ils ont choisi de fermer le problème. Le problème est dans les projets de tests unitaires. Il n'est pas utile de passer de Visual Studio Unit Testing Framework à NUnit Testing Framework.

0

Si vous utilisez l'interception d'unité et que votre paramètre est étiqueté comme sortant, l'interception d'unité provoquera cette erreur. La raison en est que Interception doit être capable de lire la liste des paramètres. Donc, comme dans le cas ci-dessus, si Resharper avertit que le paramètre peut être covariant, cet avertissement doit être ignoré.