Autofixture: NSubstitute.ReceivedCalls() mengembalikan nilai yang salah menggunakan AutoFixture.AutoNSSubstitute

Dibuat pada 28 Mar 2018  ·  10Komentar  ·  Sumber: AutoFixture/AutoFixture

Kami memiliki banyak pengujian menggunakan 'Class.ReceivedCalls()' dan 'var tmp = Class.Received(int).Property;' untuk memeriksa jumlah panggilan. Di v3 AutoFixture, ia melaporkan jumlah panggilan dengan benar, terutama Properti, yang tidak lagi dilakukan. Jumlah metode panggilan tampaknya masih ok.
Mengingat bahwa kita memiliki kode berikut:

    public interface IRunSpeed
    {
        int Speed { get; }
    }

    public class GetToDaChoppa
    {
        private readonly IRunSpeed _runSpeed;

        public GetToDaChoppa(IRunSpeed runSpeed)
        {
            _runSpeed = runSpeed ?? throw new ArgumentNullException(nameof(runSpeed));
        }

        public void DoItNow()
        {
            var runningSpeed = _runSpeed.Speed;
        }
    }

Dan mengingat bahwa kami memiliki tes berikut:

        [Fact]
        public void DoItNow_WithOutAutoNSubstitute()
        {
            // Arrange
            var runSpeed = Substitute.For<IRunSpeed>();
            runSpeed.Speed.Returns(2);

            var sut = new GetToDaChoppa(runSpeed);

            //Act
            sut.DoItNow();

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Single(runSpeed.ReceivedCalls());
        }

        [Theory, AutoNSubstituteData]
        public void DoItNow_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            sut.DoItNow();

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Single(runSpeed.ReceivedCalls());

AutoNSSubstituteDataAttribute saya terlihat seperti ini:

        public class AutoNSubstituteDataAttribute : AutoDataAttribute
        {
            public AutoNSubstituteDataAttribute()
                : base(() => new Fixture()
                           .Customize(new AutoNSubstituteCustomization()))
            {
            }
        }

Tes pertama 'DoItNow_WithOutAutoNSSubstitute' berfungsi dengan baik. Tapi tes kedua 'DoItNow_UsingAutoNSSubstitute' mengembalikan 2 untuk 'ios.Received(1).Speed;'.
Itu juga mengembalikan 2 untuk 'runSpeed.ReceivedCalls();'.
Karena itu, saat ini kami tidak dapat memutakhirkan Solusi kami ke v4 karena kami langsung memiliki> 1000 tes gagal per solusi. Adakah panduan tentang apa masalahnya atau di mana mencari perbaikan?

question

Semua 10 komentar

Terima kasih telah menyelesaikan masalah. Sebenarnya, masalah ini tidak ada hubungannya dengan AutoFixture, sementara kami juga terpengaruh olehnya

Masalah ini sebagian besar disebabkan oleh xUnit dan jika Anda menulis ulang tes sebagai berikut, itu akan lulus:
```c#
[Teori, AutoNSSubstituteData]
kekosongan publik DoItNow_UsingAutoNSSubstitute_CreateManually (Fitur Fixture)
{
// Mengatur
var runSpeed ​​= fixture.Freeze();
var sut = perlengkapan.Buat();
runSpeed.Speed.Returns(49);

//Act
sut.DoItNow();

//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Single(runSpeed.ReceivedCalls());

}
```

Saat Anda menjalankan pengujian, xUnit mencoba memformat nama pengujian untuk Anda. Jika ditemukan bahwa tipe tersebut tidak diketahui dan tidak memiliki kelebihan ToString() , ia menggunakan inspeksi struktural dan mengambil nilai properti secara rekursif. Jika Anda memeriksa nama tes, Anda akan melihat yang berikut:
image

Seperti yang mungkin Anda perhatikan, xUnit mengambil nilai properti Speed untuk menunjukkan argumen pengujian dengan baik. Karena ini adalah panggilan biasa, NSubstitute menghitungnya sebagai panggilan.

Cukup aneh bahwa Anda tidak memiliki masalah ini dengan v3, karena tidak ada yang berubah dalam hal itu. Saya baru saja menguji xUnit2 + AutoFixture v3 dan masih mendapatkan masalah. Mungkin, Anda juga telah memutakhirkan xUnit.


Adapun solusi, saya punya kabar baik dan buruk. Kabar baiknya adalah bahwa ini akan diselesaikan di versi utama NSubsitute berikutnya, karena mulai menimpa metode ToString() untuk mengembalikan id proxy. Akibatnya, xUnit tidak lagi menyentuh properti:
image

Berita buruknya adalah NSubsitute v4 belum dirilis.

Saya juga bisa menyarankan Anda:

  • tunda migrasi hingga NSubsitute v4 dirilis;
  • gunakan kode sumber master dari NSubsitute, buat build lokal dan gunakan NSubsitute.dll alih-alih paket NuGet. Setelah v4 dirilis, Anda dapat beralih ke paket NuGet.
  • jika Anda juga memperbarui versi xUnit (karena ini mungkin menjelaskan mengapa Anda tidak mengalami masalah ini sebelumnya), kembalikan perubahan itu dan gunakan versi xUnit sebelumnya.

Saya mohon maaf atas ketidaknyamanan ini, tetapi, sayangnya, kami tidak dapat melakukan apa pun di sisi AutoFixture untuk memperbaiki masalah ini.

baru saja diuji ini. akhirnya pengujian kami yang menyatakan ReceivedCalls kembali mendapatkan hasil yang sukses lagi.
Sesuatu yang masih gagal adalah pernyataan pada Received(x) seperti Received(1).Speed ​​Daniel yang disebutkan di atas.

snip_20180328181559

Apakah Anda juga punya jawaban / solusi untuk topi?

Apakah kalian mengerjakan proyek yang sama? :) Jika demikian, dapatkah Anda menjelaskan bagaimana Anda memperbaiki masalah tersebut?

Opsi yang disarankan di atas akan membantu mengatasi kedua masalah tersebut. Jika tidak - klarifikasi skenarionya.

sebenarnya bukan proyek yang sama tetapi di perusahaan yang sama.
kami telah menggunakan xunit 1.9 + nsubstitute 2 / 3 untuk waktu yang lama dan akhirnya berhasil mendapatkan rakitan internal kami (paket nuget jadi cara sederhana kembali ke versi yang lebih lama dari hanya satu referensi tidak semudah kedengarannya menjadi) agar kompatibel dengan xunit2. dan sekarang kita memiliki dua masalah ini.

Kami sudah mencoba beberapa hal dan akhirnya berpikir itu pasti ada hubungannya dengan autofixture - karena atribut beku dan jumlah eksekusi tes kode keras - atau sesuatu seperti itu.
setelah daniel membuka kasing ini, dia memberi saya tautan ke sana.

seperti yang Anda jelaskan di atas, saya mengganti referensi nuget 3.1 dengan referensi dari proyek nsubstitute yang baru dikompilasi. setelah itu saya sekarang memiliki 118 alih-alih 178 tes yang gagal karena Receiced(x) masih mengevaluasi jumlah panggilan yang salah.

proyek saya saat ini didasarkan pada .net 4.5.2 dengan xunit2, versi repo saat ini dari nsubstitute dan autofixture 4.2 direferensikan. semua tes gagal karena dua alasan yang sama - juga masih ada beberapa panggilan yang diterima gagal dalam tes unit.
Saya pikir saya harus melihat lebih dalam lagi ketika saya kembali ke kantor lagi (keluar untuk paskah).
mungkin @dklinger sementara itu bisa menggambarkan skenarionya.

@dklinger @evilbaschdi Harap tindak lanjuti setelah Anda memiliki kesempatan untuk memeriksanya - cukup menarik mengapa Anda masih melihat masalah, bahkan setelah Anda menerapkan tambalan.

Buka kembali masalah untuk menunjukkan bahwa kami masih memiliki penyelidikan yang sedang berlangsung.

Ok, jadi saya sudah menguji beberapa jam terakhir. Pertama: Terima kasih atas balasan Anda, penjelasan dan saran Anda - yang sangat membantu.
Saya telah menguji v4 dari NSubstitute. Ini berfungsi untuk kode contoh saya di atas, tetapi tidak menyelesaikan masalah sepenuhnya di proyek dunia nyata kami. Masalahnya adalah, itu menyelesaikan masalah jumlah ReceivedCalls yang salah hanya untuk SUT-Calls ke metode, bukan ke properti.

Contoh kode kami yang sekarang berfungsi:

        [Theory, AutoNSubstituteData]
        public void DoItNow_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            sut.DoItNow();

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Equal(1, runSpeed.ReceivedCalls().Count());
        }

Tetapi jika saya mengubah metode "GetToDaChoppa.DoItNow();" menjadi properti "GetToDaChoppa.DoItNow" ReceivedCallsCount adalah +1 lagi:

        [Theory, AutoNSubstituteData]
        public void DoItNow_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            var x = sut.DoItNow;

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Equal(1, runSpeed.ReceivedCalls().Count());
        }

Saya pikir itu lagi ada hubungannya dengan penamaan xUnit saat kita mendapatkan yang ini untuk implementasi metode kerja:
image

Dan yang itu untuk implementasi properti yang tidak berfungsi:
image

Sepertinya xUnit memanggil properti SUT untuk mengambil nilainya untuk menggunakannya untuk nama tes tetapi tidak melakukan ini untuk metode SUT. Pikiran pertama saya adalah bahwa itu ada hubungannya dengan nilai pengembalian metode kami "GetToDaChoppa()" yang batal. Tetapi bahkan setelah mengubahnya menjadi "public int GetToDaChoppa()" xUnit masih tidak memanggilnya untuk mendapatkan nilai kembalian untuk Nama pengujian. Ini hanya masalah menggunakan properti.

Untuk saat ini saya terjebak lagi. Saya sangat setuju bahwa ini bukan masalah AutoFixture. Tetapi menurut Anda, mengetahui semua paket lebih baik daripada kami, apa saran Anda?

  • membuka masalah untuk NSubstitute?
  • membuka masalah untuk xUnit2?
  • atau sesuatu yang sama sekali baru?

@dklinger Terima kasih atas tindak lanjutnya! Bisakah Anda membagikan kode MCVE untuk skenario terakhir yang masih gagal? Hanya untuk memastikan tidak ada yang terlewatkan dan saya tidak salah memahami kondisinya.

Setelah itu saya akan mencoba menyelidiki mengapa itu terjadi dan bagaimana cara mengatasinya.

Terima kasih.

Ya, tentu. Ini dia:

Sistem di bawah Uji:

    public interface IRunSpeed
    {
        int Speed { get; }
        void Dude();
        int Dude2();
    }

    public class GetToDaChoppa
    {
        private readonly IRunSpeed _runSpeed;

        public GetToDaChoppa(IRunSpeed runSpeed)
        {
            _runSpeed = runSpeed ?? throw new ArgumentNullException(nameof(runSpeed));
        }

        public int DoItNow
        {
            get
            {
                var runningSpeed = _runSpeed.Speed;
                return 0;
            }
        }
    }

Kasus cobaan:

        [Theory, AutoNSubstituteData]
        public void DoItNowAsProperty_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            var x = sut.DoItNow;

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Equal(1, runSpeed.ReceivedCalls().Count());
        }

Saat ini saya mencoba mengikuti diskusi di https://github.com/xunit/xunit/issues/1386 dan https://github.com/AutoFixture/AutoFixture/issues/805. Mungkin kami melakukan sesuatu yang salah atau ada cara untuk memberi tahu xUnit agar tidak membuat nama pengujian secara otomatis.
Saya juga mencoba membuat TheoryAttribute saya sendiri dengan mengesampingkan properti DisplayName tetapi itu tidak membantu karena xUnit dalam beberapa hal masih menggunakan nama yang dibuat secara otomatis secara internal. Tapi itu hanya fyi dan sama sekali tidak terkait dengan kode demo di atas.

        public sealed class MyTheoryAttribute : TheoryAttribute
        {
            public MyTheoryAttribute([CallerMemberName] string memberName = null)
            {
                DisplayName = "MyTestCase";
            }
        }

image

Halo, saya lagi :)
Memang xUnit2 memanggil semua Properti dan Bidang parameter metode-tes yang merupakan Tipe Kompleks. Baris kodenya adalah ini: https://github.com/xunit/assert.xunit/blob/2b70a9b0c5bb291f98472ec24cec437acf8d65c8/Sdk/ArgumentFormatter.cs#L156

Terima kasih atas dukunganmu. Saya telah membuka kembali masalah di xUnit-Repo tempat diskusi harus berlangsung: https://github.com/xunit/xunit/issues/1682

@dklinger Terima kasih atas skenario terperincinya. Ini memang cukup rumit dan sulit untuk mengatasinya. Dari perspektif AutoFixture dan NSubsitute, tidak ada perbedaan apakah kode dipanggil di suatu tempat jauh di dalam xUnit atau di badan uji.

Biasanya, sebagai solusinya, Anda dapat menggunakan fitur clear NSubstitute:

runSpeed.ClearReceivedCalls();

Kode ini harus dijalankan pada awal setiap tes di mana Anda memverifikasi jumlah panggilan yang tepat. Ini berfungsi dengan baik jika Anda memiliki beberapa tes, namun jelas, jika ribuan tes terpengaruh, itu tidak akan banyak membantu

Sangat disayangkan bahwa integrasi NSubsitute + xUnit2 + AutoFixture tidak berfungsi dengan baik dan mengalami masalah seperti ini. Produk AutoFixture dirancang untuk menyederhanakan hidup, bukan untuk membuatnya menjadi mimpi buruk Harap orang-orang dari xUnit akan memberi tahu Anda cara cepat untuk menyelesaikan masalah untuk keseluruhan proyek.

Beri tahu saya jika Anda yakin kami dapat melakukan sesuatu dari pihak kami untuk memperbaiki situasi.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

malylemire1 picture malylemire1  ·  7Komentar

josh-degraw picture josh-degraw  ·  4Komentar

mjfreelancing picture mjfreelancing  ·  4Komentar

Ridermansb picture Ridermansb  ·  4Komentar

zvirja picture zvirja  ·  4Komentar