Unit menguji metode internal di VS2017. Standar Net library

150

Saat ini saya sedang bermain-main dengan Kandidat Rilis Visual Studio 2017 terbaru dengan membuat pustaka .Net Standar 1.6. Saya menggunakan xUnit untuk menguji unit kode saya dan bertanya-tanya apakah Anda masih dapat menguji metode internal di VS2017.

Saya ingat bahwa Anda bisa semua kelas AssemblyInfo.cs garis di VS2015 yang akan memungkinkan proyek yang ditentukan untuk melihat metode internal

[assembly:InternalsVisibleTo("MyTests")]

Karena tidak ada kelas AssemblyInfo.cs di VS2017. Proyek standar Net Saya bertanya-tanya apakah Anda masih dapat menguji metode internal unit?

Phil Murray
sumber
3
Anda harus dapat menguji unit kode Anda dari fungsionalitas yang terlihat secara eksternal saja. Lagi pula, jika tidak ada jalur logis dari kode eksternal yang dapat mencapai metode internal itu, apa yang akan mereka lakukan di sana?
David
3
@ David Saya dapat dan telah melakukan ini, tetapi saya telah melakukan tes unit sederhana di sekitar beberapa kelas internal sebelumnya. Agar lebih eksplisit dalam pengujian.
Phil Murray
5
AFAIK, Anda dapat menempatkan atribut ini di file lain, di luar namespaceblok, dan itu harus dikompilasi. Seharusnya tidak ada yang ajaib tentang itu AssemblyInfo.cs. Tidak berhasil? Tentu saja, Anda perlu menambahkan usingklausa yang benar atau menggunakan atribut yang sepenuhnya memenuhi syarat [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")].
Groo
1
@ David Jika Anda membuat perpustakaan dengan kelas internal dan Anda perlu menguji dan mengejek kelas-kelas ini, InternalsVisibleTosangat penting - misalnya di sini - stackoverflow.com/a/17574183/43453
PandaWood

Jawaban:

210

Menurut .NET docs untukInternalsVisibleToAttribute :

Atribut diterapkan pada tingkat perakitan. Ini berarti bahwa itu dapat dimasukkan pada awal file kode sumber, atau dapat dimasukkan dalam file AssemblyInfo dalam proyek Visual Studio.

Dengan kata lain, Anda cukup meletakkannya di file .cs Anda yang dinamai secara sewenang-wenang, dan itu akan berfungsi dengan baik:

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]
Groo
sumber
1
@ PhilMurray: juga, sepertinya ada pengaturan yang memungkinkan Anda untuk membuat file "klasik" AssemblyInfo.csseperti dijelaskan di sini . Kalau tidak, semua atribut seperti "deskripsi", "hak cipta", dan hal-hal lain disimpan di dalam file .csproj.
Groo
43

Seperti yang dijelaskan di sini:

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

Dimungkinkan untuk menambahkan atribut terlihat internal dalam file proyek dengan menambahkan ItemGroup lain:

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

atau bahkan:

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

Saya suka solusi itu karena file proyek tampaknya menjadi tempat yang tepat untuk mendefinisikan masalah tersebut.

JanDotNet
sumber
8

Sementara jawaban pertama baik-baik saja. Jika Anda merasa masih ingin melakukan ini dalam aslinya, AssemblyInfoAnda selalu dapat memilih untuk tidak membuat file secara otomatis dan menambahkannya secara manual.

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

Untuk informasi lebih lanjut: https://stackoverflow.com/a/47075759/869033

Nick N.
sumber
5

Atribut "InternalsVisibleTo" adalah kunci untuk segala jenis "kotak putih" (istilah dekade ini, saya kira) pengujian untuk. Net. Itu dapat ditempatkan di file c # apa saja dengan atribut "assembly" di bagian depan. Perhatikan bahwa MS DOC mengatakan bahwa nama rakitan harus memenuhi syarat oleh token kunci publik, jika ditandatangani. Terkadang itu tidak berhasil dan seseorang harus menggunakan kunci publik penuh di tempatnya. Akses ke internal adalah kunci untuk menguji sistem bersamaan dan dalam banyak situasi lainnya. Lihat https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 . Dalam buku ini, Meszaros menjelaskan berbagai gaya pengkodean yang pada dasarnya merupakan pendekatan "Desain Untuk Uji" untuk pengembangan program. Setidaknya itulah cara saya menggunakannya selama bertahun-tahun.

TAMBAH: Maaf, saya belum berada di sini untuk sementara waktu. Salah satu pendekatan disebut pendekatan "pengujian subclass" oleh Meszaros. Sekali lagi, kita harus menggunakan "internalsvisableto" untuk mengakses internal kelas dasar. Ini adalah solusi yang bagus, tetapi tidak berfungsi untuk kelas yang disegel. Ketika saya mengajar "Desain Untuk Tes", saya menyarankan bahwa itu adalah salah satu hal yang diperlukan untuk "pra-rekayasa" ke dalam kelas dasar untuk memberikan testabilitas. Itu harus menjadi hampir hal budaya. Desain kelas dasar "basis" yang tidak disegel. Sebut saja UnsealedBaseClass atau sesuatu yang dapat dikenali secara seragam. Ini adalah kelas yang akan disubklasifikasikan untuk pengujian. Itu juga subkelas untuk membangun kelas disegel produksi, yang sering hanya berbeda dalam konstruktor yang mengekspos. Saya bekerja di industri nuklir dan persyaratan pengujian ditanggapi SANGAT serius. Jadi, saya harus memikirkan hal-hal ini setiap saat. By the way, meninggalkan kait pengujian dalam kode produksi tidak dianggap sebagai masalah di bidang kami, asalkan mereka "internal" dalam implementasi .Net. Konsekuensi TIDAK menguji sesuatu bisa sangat mendalam.

kurt.matis
sumber
1

Cara lain adalah dengan menggunakan kelas publik TestMyFoo 'wrapper' di dalam proyek target yang memiliki metode publik dan pewarisan dari kelas yang perlu Anda uji (misalnya MyFoo). Metode publik ini hanya memanggil kelas dasar yang ingin Anda uji.

Ini tidak 'ideal' karena Anda akhirnya mengirim kait uji di proyek target Anda. Tetapi pertimbangkan mobil modern yang andal dikirimkan dengan port diagnostik dan kapal elektronik modern yang andal dengan koneksi JTAG. Tapi tidak ada yang cukup konyol untuk mengendarai mobil mereka menggunakan port diagnostik.

andrew pate
sumber