Autofixture: Menerapkan kustomisasi dari kelas dasar atau antarmuka gagal di 4.0.0-rc1 (regresi)

Dibuat pada 20 Nov 2017  ·  10Komentar  ·  Sumber: AutoFixture/AutoFixture

Tes berikut berhasil di AutoFixture 3.51.0 tetapi gagal di 4.0.0-rc1 :
(bahkan dalam komit terbaru di master: c856cd6 )

``` c#
[Fakta]
public void ShouldApplyCustomizationsFromBaseClass()
{
var perlengkapan = Perlengkapan baru();
perlengkapan. Sesuaikan(c => c.Tanpa(bc => bc.Id));
var res = perlengkapan.Buat();
Assert.Equal(0, res.Id);
}

[Fakta]
public void ShouldApplyCustomizationsFromInterface()
{
var perlengkapan = Perlengkapan baru();
perlengkapan. Sesuaikan(c => c.Tanpa(bc => bc.Id));
var res = perlengkapan.Buat();
Assert.Equal(0, res.Id);
}

antarmuka publik IInterface
{
int Id { dapatkan; mengatur; }
}

Kelas Dasar kelas publik
{
publik int Id { dapatkan; mengatur; }
}

kelas publik ImplClass : BaseClass, IInterface
{

}
```

question

Semua 10 komentar

Terima kasih telah mengajukan pertanyaan. Nah, ini adalah perubahan yang diinginkan dan telah diterapkan dengan sengaja.

Sebelumnya kami memiliki masalah ketika kustomisasi satu sub-tipe dapat mempengaruhi sub-tipe lainnya. Contohnya:

```c#
class Base { public string Umum { get; mengatur; } }
kelas Anak1: Basis {}
kelas Anak2: Basis {}

[Fakta]
public void PastikanCustomizationAreNotAffected()
{
var perlengkapan = Perlengkapan baru();
perlengkapan. Sesuaikan(c => c.Dengan(x => x.Umum, "boneka"));

var result = fixture.Create<Child2>();

Assert.NotNull(result.Common);

}


In the v3 this test failed, causing a lot of confusion to people. As you might imagine, the scenarios were more complicated and it was very non-obvious why the particular members are not initialized. 

For instance, the following code will not work, which again proves that API is not designed for that.
```c#
fixture.Customize<Base>(c => c.With(x => x.Common, "foo"));

Oleh karena itu, untuk memperbaiki masalah itu, kami mengubah pendekatan , sehingga sekarang penyesuaian satu jenis tidak dapat memengaruhi jenis lain, meskipun mereka termasuk dalam garis pewarisan yang sama. Seperti yang mungkin Anda lihat di PR itu, itu memperbaiki banyak masalah kegunaan dan menambahkan lebih banyak kejelasan (sementara perubahan itu memang melanggar).

Jika Anda masih ingin menghilangkan properti basis/antarmuka, Anda dapat menggunakan cuplikan berikut:
```c#
private class SamePropertySpecification : IRequestSpecification
{
pribadi hanya bisa dibaca Type _declaringType;
string hanya-baca pribadi _name;

public SamePropertySpecification(Type declaringType, string name)
{
    _declaringType = declaringType;
    _name = name;
}

public bool IsSatisfiedBy(object request)
{
    if (request is PropertyInfo pi)
    {
        return pi.DeclaringType == this._declaringType &&
               pi.Name.Equals(this._name, StringComparison.Ordinal);
    }

    return false;
}

}

[Fakta]
kekosongan publik TestBasePropertyOmitting()
{
var perlengkapan = Perlengkapan baru();

fixture.Customizations.Add(new Omitter(new SamePropertySpecification(typeof(Base), nameof(Base.Common))));

var result = fixture.Create<Child1>();
Assert.Null(result.Common);

}
```

Jika Anda sering membutuhkan fitur itu, Anda dapat membuat metode ekstensi Anda sendiri untuk fixture . Namun, saya memilih untuk tidak memiliki fitur out-of-the-box, karena terlihat sangat membingungkan.

Oke, bagus untuk mengetahui itu disengaja. Saya sangat setuju bahwa itu membingungkan, tetapi jika itu dapat diterapkan secara eksplisit, itu adalah fitur yang bagus. Akan mencoba cuplikan Anda (dan mungkin akan membuat metode ekstensi).

Omong-omong: Apakah ini sesuatu yang ingin Anda tambahkan ke daftar perubahan yang melanggar? Mungkin mencegah pertanyaan yang sama diajukan.

Tidak ada cara untuk ikut serta dalam perilaku lama untuk salah satu penyesuaian dari semua penyesuaian, bukan?

Apakah ini sesuatu yang ingin Anda tambahkan ke daftar perubahan yang melanggar?

Nah, itu disebutkan di bagian perbaikan bug . Ini sebenarnya bukan perubahan yang melanggar, karena perilaku sebelumnya tidak pernah dinyatakan sebagai "fitur". Sebaliknya, itu adalah efek samping yang tidak diinginkan dan akhirnya dihilangkan

Tidak ada cara untuk ikut serta dalam perilaku lama untuk salah satu penyesuaian dari semua penyesuaian, bukan?

Tidak, tidak ada cara yang saya yakini karena saya benar-benar mengerjakan ulang pendekatannya.

Silakan uji cuplikan dan jika berhasil - jangan ragu untuk menutup masalah. Atau beri tahu saya jika Anda memiliki pertanyaan lebih lanjut

Saya telah mengubahnya sehingga juga berfungsi untuk antarmuka dan membuat metode ekstensi sehingga dapat digunakan di 'Fixture.Customize(...)'. Terasa sedikit lebih hacky daripada yang saya inginkan, terutama karena cara kerjanya di v3 sempurna bagi kami. Tetapi karena satu-satunya kasus penggunaan kami adalah menghilangkan properti dan (yang paling penting ) berfungsi, itu akan berhasil. Terima kasih!

@nphmuller Maaf saya telah melanggar kode rapi dan rapi Anda dan sekarang Anda harus bertahan Tapi saya percaya bahwa pengorbanan Anda dibuat untuk kebaikan kita semua, jadi Anda tidak akan terlalu menyalahkan kami

Tidak menyalahkan sama sekali. Pahami alasan Anda dengan sempurna dan bahkan setuju. Hanya menyebalkan bagi saya

Mungkin menyelami masalah nanti untuk melihat ada cara yang lebih rapi. Untuk saat ini baik-baik saja.

Hanya ingin tahu - apa kasus penggunaan Anda yang sebenarnya untuk itu? Karena saya tidak pernah memenuhi kebutuhan dalam fungsi seperti itu.. Biasanya, ketika saya menulis tes, saya hanya perlu menyesuaikan tipe tertentu, daripada mengkonfigurasi tipe dasar atau antarmuka. Apakah menulis semacam penyesuaian global?

Dalam hal ini kami menggunakan AutoFixture sebagai generator data pengujian untuk pengujian integrasi Entity Framework.

Kami memiliki beberapa tipe dasar atau antarmuka yang digunakan entitas kami yang berisi properti umum. Id, tenant-id (dan properti navigasi), hal-hal seperti itu.

Misalnya, salah satu properti ini adalah pengguna mana yang membuat objek. Properti ini tidak begitu menarik untuk sebagian besar pengujian, dan jika dibuat, ia akan membuat grafik besar (kelas Pengguna juga memiliki banyak properti navigasi) yang harus dibuat dan dimasukkan ke dalam database. Ini akan membuat tes lambat atau bahkan gagal pada level db karena objek tidak dimaksudkan untuk dimasukkan seperti itu.

Jadi lebih mudah untuk mengecualikan properti ini dan ikut serta bila perlu. Pada tingkat kelas dasar, karena aturan penghilangan yang sama harus ditulis untuk setiap tipe entitas.

@nphmuller Terima kasih atas klarifikasinya, sekarang sudah jelas Ya, sepertinya skenarionya masuk akal, tapi harus saya akui sepertinya sesuatu yang sangat jarang Anda butuhkan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

Accc99 picture Accc99  ·  4Komentar

ploeh picture ploeh  ·  7Komentar

zvirja picture zvirja  ·  8Komentar

JoshKeegan picture JoshKeegan  ·  6Komentar

Eldar1205 picture Eldar1205  ·  5Komentar