VS2017 .Net Standard kitaplığında dahili yöntemleri test eden birim


154

Şu anda bir .Net Standard 1.6 kitaplığı oluşturarak en son Visual Studio 2017 Sürüm Adayı ile uğraşıyorum. Kodumu test etmek için xUnit kullanıyorum ve hala VS2017'de dahili yöntemleri test edip edemeyeceğinizi merak ediyordum.

VS2015'teki tüm bir satır AssemblyInfo.cs sınıfının, belirtilen projelerin dahili yöntemleri görmesini sağlayabileceğini hatırlıyorum.

[assembly:InternalsVisibleTo("MyTests")]

VS2017 .Net Standard projelerinde AssemblyInfo.cs sınıfı olmadığından, hala dahili yöntemleri birim test edip edemeyeceğinizi merak ediyordum?


3
Sen olmalıdır yalnız dıştan görülebilen işlevlerinden birim test Kodunuzdaki muktedir. Sonuçta, harici koddan mantıksal bir yol bu dahili yöntemlere ulaşamıyorsa, o zaman ilk başta orada ne yapıyor olacaklar?
David

4
@David Yapabilirim ve bunu yaptım ama daha önce bazı dahili sınıfların etrafına basit birim testleri koymuştum. Testte daha açık olmak için.
Phil Murray

5
AFAIK, bu özniteliği namespacebloğun dışında başka herhangi bir dosyaya yerleştirebilirsiniz ve derlemelidir. Büyülü bir şey olmamalı AssemblyInfo.cs. Çalışmıyor mu? Elbette, doğru usingmaddeyi eklemeniz veya tam nitelikli özelliği kullanmanız gerekir [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")].
Groo

1
@David Dahili sınıflar içeren bir kitaplık oluşturuyorsanız ve bu sınıfları test etmeniz ve alay etmeniz gerekiyorsa InternalsVisibleTo, kritik öneme sahiptir - örneğin burada - stackoverflow.com/a/17574183/43453
PandaWood

Yanıtlar:


218

.NET belgelerineInternalsVisibleToAttribute göre :

Nitelik, montaj düzeyinde uygulanır. Bu, bir kaynak kod dosyasının başlangıcına dahil edilebileceği veya bir Visual Studio projesindeki AssemblyInfo dosyasına dahil edilebileceği anlamına gelir.

Başka bir deyişle, onu rastgele adlandırılmış kendi .cs dosyanıza yerleştirebilirsiniz ve sorunsuz çalışmalıdır:

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]

1
@PhilMurray: Ayrıca, buradaAssemblyInfo.cs açıklandığı gibi "klasik" bir dosya oluşturmanıza izin verecek bir ayar var gibi görünüyor . Aksi takdirde, "açıklama", "telif hakkı" ve diğer şeyler gibi tüm öznitelikler .csproj dosyasında saklanır.
Groo

53

Burada açıklandığı gibi:

https://blog.sanderaernouts.com/make-internals-visible-with-new-csproj-format

Başka bir ÖğeGrubu ekleyerek dahili görünür özniteliği proje dosyasına eklemek mümkündür:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(AssemblyName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

ya da:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

Bu çözümü seviyorum çünkü proje dosyası bu tür endişeleri tanımlamak için doğru yer gibi görünüyor.


8

İlk cevap gayet iyi olsa da. Orijinalde bunu hala yapmak istediğinizi düşünüyorsanız AssemblyInfo, dosyayı her zaman otomatik olarak oluşturmamayı ve manuel olarak eklemeyi seçebilirsiniz.

<PropertyGroup>
   <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Daha fazla bilgi için: https://stackoverflow.com/a/47075759/869033


5

"InternalsVisibleTo" özniteliği, .Net için her tür "beyaz kutu" (sanırım on yılın terimi) testinin anahtarıdır. Önde "assembly" özniteliği olan herhangi bir c # dosyasına yerleştirilebilir. MS DOC'ların, eğer imzalanmışsa, derleme adının ortak anahtar belirteci tarafından nitelendirilmesi gerektiğini söylediğini unutmayın. Bazen bu işe yaramaz ve kişinin yerinde tam açık anahtarı kullanması gerekir. Dahili bileşenlere erişim, eşzamanlı sistemleri test etmek ve diğer birçok durumda anahtardır. Bkz. Https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 . Bu kitapta Meszaros, temelde program geliştirmeye yönelik "Test İçin Tasarım" yaklaşımını oluşturan çeşitli kodlama stillerini açıklamaktadır. En azından yıllarca bunu kullandım.

ADDED: Üzgünüm, bir süredir burada değildim. Bir yaklaşım Meszaros tarafından "alt sınıf test etme" yaklaşımı olarak adlandırılır. Yine, temel sınıfın dahili öğelerine erişmek için "internalsvisableto" kullanmak gerekir. Bu harika bir çözüm, ancak kapalı sınıflarda işe yaramıyor. "Test İçin Tasarım" öğrettiğimde, bunun test edilebilirliği sağlamak için temel sınıflara "önceden tasarlanmış" olması gereken şeylerden biri olduğunu öneriyorum. Neredeyse kültürel bir şey haline gelmelidir. Mühürsüz bir "temel" temel sınıf tasarlayın. Buna UnsealedBaseClass veya tek tip olarak tanınan bir şey deyin. Bu, test için alt sınıfa alınacak sınıftır. Ayrıca, genellikle yalnızca ortaya çıkardığı kurucularda farklılık gösteren sızdırmaz üretim sınıfını oluşturmak için alt sınıflara ayrılır. Nükleer endüstride çalışıyorum ve test gereksinimleri ÇOK ciddiye alınıyor. Bu yüzden her zaman bunları düşünmem gerekiyor. Bu arada, bir .Net uygulamasında "dahili" oldukları sürece, üretim kodunda test kancalarını bırakmak bizim alanımızda bir sorun olarak görülmemektedir. Bir şeyi test ETMEMENİN sonuçları oldukça derin olabilir.


1

Başka bir yol da, test etmeniz gereken sınıftan (örneğin MyFoo) genel yöntemler ve miras alan hedef proje içinde bir 'sarmalayıcı' TestMyFoo genel sınıfı kullanmaktır. Bu genel yöntemler, test etmek istediğiniz temel sınıfı çağırır.

Hedef projenizde bir test kancası göndereceğiniz için 'ideal' değildir. Ancak, teşhis portları ve JTAG bağlantılı modern güvenilir elektronikler ile gönderilen modern güvenilir arabaları düşünün. Ama hiç kimse arabasını teşhis portunu kullanarak sürecek kadar aptal değil.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.