سؤال

لقد بدأت مؤخرا باستخدام أوتوفيكستوري + أوتوموك وأنا أحاول إنشاء مثيل من Func<IDbConnection> (أي مصنع اتصال).

var fixture = new Fixture().Customize(new AutoMoqCustomization());
var connectionFactory = fixture.Create<Func<IDbConnection>>();

يبدو أن هذا يعمل بشكل جيد:

  1. نظام بلدي تحت الاختبار يمكن استدعاء المندوب وسوف تحصل على وهمية من IDbConnection
  2. التي يمكنني الاتصال بها بعد ذلك CreateCommand, ، والتي سوف تحصل لي وهمية من IDbCommand
  3. التي يمكنني الاتصال بها بعد ذلك ExecuteReader, ، والتي سوف تحصل لي وهمية من IDataReader

أريد الآن إجراء إعدادات إضافية على وهمية IDataReader, ، مثل جعله يعود true عندما Read() يسمى.

من ما قرأته ، يجب أن أستخدم Freeze لهذا:

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();

dataReaderMock.Setup(dr => dr.Read())
                      .Returns(true);

هذا لا يبدو لتلبية توقعاتي على الرغم من.عندما أتصل IDbCommand.ExecuteReader, ، سأحصل على قارئ مختلف عن القارئ الذي جمدته/أعده للتو.

هنا مثال:

var fixture = new Fixture().Customize(new AutoMoqCustomization());

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
              .Returns(true);

//true - Create<IDataReader> retrieves the data reader I just mocked
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDataReader>());

//false - IDbCommand returns a different instance of IDataReader
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());

ماذا أفعل خطأ?كيف يمكنني الحصول على تركيبات أخرى ، مثل IDbCommand, ، لاستخدام مثيل سخر من IDataReader?

هل كانت مفيدة؟

المحلول

اعتبارا من 3.20.0 ، يمكنك استخدام AutoConfiguredMoqCustomization.سيؤدي هذا تلقائيا إلى تكوين جميع الاستهزاء بحيث يتم إنشاء قيم إرجاع أعضائها عن طريق التثبيت التلقائي.

على سبيل المثال., IDbConnetion.CreateCommand سيتم تكوينه تلقائيا لإرجاع ملف IDbCommand من المباراة ، و IDbCommand.ExecuteReader سيتم تكوينه تلقائيا لإرجاع ملف IDataReader من المباراة.

كل هذه الاختبارات يجب أن تمر الآن:

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());

var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
              .Returns(true);

//all pass
Assert.Same(dataReaderMock.Object, fixture.Create<IDataReader>());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbConnection>().CreateCommand().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<Func<IDbConnection>>()().CreateCommand().ExecuteReader());

نصائح أخرى

عليك أن Freeze ال Mock<IDbCommand> كذلك-وإعداد الكائن وهمية (كما كعب) لإرجاع القائمة dataReaderMock.Object على سبيل المثال.

إذا قمت بإضافة ما يلي إلى مرحلة ترتيب الاختبار ، فسوف يمر الاختبار:

var dbCommandStub = 
    fixture
        .Freeze<Mock<IDbCommand>>()
        .Setup(x => x.ExecuteReader())
        .Returns(dataReaderMock.Object);

في حين أن الحل من نيكوس يعمل وأود أن لا أنا لا أوصي السخرية ado.net.

في رأيي ، من المحتمل أن يكون من الصعب فهم اختباراتك والحفاظ عليها ولن تمنحك الثقة التي يجب أن توفرها لك اختباراتك.

وأود أن تنظر في اختبار طبقة البيانات الخاصة بك عن طريق الذهاب على طول الطريق إلى قاعدة البيانات على الرغم من أنه أبطأ.

أوصي بقراءة هذه المقالة فيما يتعلق بأفضل الممارسات للسخرية:http://codebetter.com/jeremymiller/2006/01/10/best-and-worst-practices-for-mock-objects/

لا تسخر من الآخرين:http://aspiringcraftsman.com/2012/04/01/tdd-best-practices-dont-mock-others/

لا أعرف وضعك بالضبط ولكن على أي حال أردت مشاركة هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top