মোকের সাথে একটি নির্দিষ্ট পরামিতি যাচাই করা


168
public void SubmitMessagesToQueue_OneMessage_SubmitSuccessfully()
{
    var messageServiceClientMock = new Mock<IMessageServiceClient>();
    var queueableMessage = CreateSingleQueueableMessage();
    var message = queueableMessage[0];
    var xml = QueueableMessageAsXml(queueableMessage);
    messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(xml)).Verifiable();
    //messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(It.IsAny<XmlElement>())).Verifiable();

    var serviceProxyFactoryStub = new Mock<IMessageServiceClientFactory>();
    serviceProxyFactoryStub.Setup(proxyFactory => proxyFactory.CreateProxy()).Returns(essageServiceClientMock.Object);
    var loggerStub = new Mock<ILogger>();

    var client = new MessageClient(serviceProxyFactoryStub.Object, loggerStub.Object);
    client.SubmitMessagesToQueue(new List<IMessageRequestDTO> {message});

    //messageServiceClientMock.Verify(proxy => proxy.SubmitMessage(xml), Times.Once());
    messageServiceClientMock.Verify();
}

আমি মোক ব্যবহার শুরু করছি এবং কিছুটা লড়াই করছি। আমি এই বার্তাটি সার্ভিসক্লিয়েন্টটি সঠিক প্যারামিটারটি গ্রহণ করছে যা যাচাই করার চেষ্টা করছি যা একটি এক্সএমএল উপাদান, তবে এটি কার্যকর করার কোনও উপায় আমি খুঁজে পাচ্ছি না। এটি তখনই কাজ করে যখন আমি কোনও নির্দিষ্ট মান পরীক্ষা করি না।

কোন ধারনা?

আংশিক উত্তর: আমি পরীক্ষার একটি উপায় খুঁজে পেয়েছি যে প্রক্সিটিতে প্রেরিত এক্সএমএলটি সঠিক, তবে এখনও আমি এটি করার সঠিক উপায় বলে মনে করি না।

public void SubmitMessagesToQueue_OneMessage_SubmitSuccessfully()
{
    var messageServiceClientMock = new Mock<IMessageServiceClient>();
    messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(It.IsAny<XmlElement>())).Verifiable();
    var serviceProxyFactoryStub = new Mock<IMessageServiceClientFactory>();
    serviceProxyFactoryStub.Setup(proxyFactory => proxyFactory.CreateProxy()).Returns(messageServiceClientMock.Object);
    var loggerStub = new Mock<ILogger>();

    var client = new MessageClient(serviceProxyFactoryStub.Object, loggerStub.Object);
    var message = CreateMessage();
    client.SubmitMessagesToQueue(new List<IMessageRequestDTO> {message});

    messageServiceClientMock.Verify(proxy => proxy.SubmitMessage(It.Is<XmlElement>(xmlElement => XMLDeserializer<QueueableMessage>.Deserialize(xmlElement).Messages.Contains(message))), Times.Once());
}

যাইহোক, আমি কীভাবে যাচাই কলটি থেকে অভিব্যক্তিটি বের করতে পারি?

উত্তর:


250

যদি যাচাইয়ের যুক্তিটি তুচ্ছ না হয়, তবে একটি বৃহত ল্যাম্বডা পদ্ধতিটি লিখতে অসুবিধা হবে (যেমন আপনার উদাহরণটি দেখায়)। আপনি সমস্ত পরীক্ষার স্টেটমেন্টগুলি পৃথক পদ্ধতিতে রাখতে পারেন তবে আমি এটি করতে পছন্দ করি না কারণ এটি পরীক্ষার কোডটি পড়ার প্রবাহকে ব্যাহত করে।

আর একটি বিকল্প হ'ল উপহাস পদ্ধতিতে উত্তীর্ণ হওয়া মানটি সংরক্ষণ করার জন্য সেটআপ কলটিতে কলব্যাক ব্যবহার করা এবং তারপরে Assertযাচাই করার জন্য মানক পদ্ধতিগুলি লিখুন । উদাহরণ স্বরূপ:

// Arrange
MyObject saveObject;
mock.Setup(c => c.Method(It.IsAny<int>(), It.IsAny<MyObject>()))
        .Callback<int, MyObject>((i, obj) => saveObject = obj)
        .Returns("xyzzy");

// Act
// ...

// Assert
// Verify Method was called once only
mock.Verify(c => c.Method(It.IsAny<int>(), It.IsAny<MyObject>()), Times.Once());
// Assert about saveObject
Assert.That(saveObject.TheProperty, Is.EqualTo(2));

6
এই পদ্ধতির একটি বড় সুবিধা হ'ল এটি আপনাকে কীভাবে ভুলটি (যেমন আপনি প্রতিটি স্বতন্ত্রভাবে পরীক্ষা করছেন) এর জন্য নির্দিষ্ট পরীক্ষা ব্যর্থতা দেয়।
রব চার্চ

1
আমি ভেবেছিলাম যে আমিই এই কাজটি করেছি, এটি যুক্তিসঙ্গত পদ্ধতির দেখে খুশি!
অ্যাপলবি

3
আমি মনে করি এটি মায়ো অনুসারে <MyObject> (যাচাইকারক) ব্যবহার করা আরও ভাল কারণ এটি
ল্যাম্বদার

এই থ্রেডটি কি নিরাপদ, উদাহরণস্বরূপ যখন সমান্তরালে পরীক্ষা চালাচ্ছে?
আন্তন টলকেন

@ অ্যান্টন টলকেন আমি এটি চেষ্টা করে দেখিনি, তবে আমার উদাহরণে, অবজেক্টটি আপডেট করা হয়েছে এটি একটি স্থানীয় ভেরিয়েবল (সেভওজেক্ট) তাই এটি থ্রেডটি নিরাপদ হওয়া উচিত।
ধনী তেব্ব

111

আমি একই পদ্ধতিতে কলগুলি যাচাই করে দেখছি - আমি বিশ্বাস করি এটি করা সঠিক উপায়।

mockSomething.Verify(ms => ms.Method(
    It.IsAny<int>(), 
    It.Is<MyObject>(mo => mo.Id == 5 && mo.description == "test")
  ), Times.Once());

যদি আপনার ল্যাম্বডা এক্সপ্রেশনটি অমনোযোগী হয়ে যায়, আপনি এমন একটি ফাংশন তৈরি করতে পারেন যা MyObjectইনপুট এবং আউটপুট true/ false... হিসাবে গ্রহণ করে

mockSomething.Verify(ms => ms.Method(
    It.IsAny<int>(), 
    It.Is<MyObject>(mo => MyObjectFunc(mo))
  ), Times.Once());

private bool MyObjectFunc(MyObject myObject)
{
  return myObject.Id == 5 && myObject.description == "test";
}

এছাড়াও, মোক সহ একটি বাগ সম্পর্কে সচেতন থাকুন যেখানে ত্রুটি বার্তাটি জানিয়েছে যে পদ্ধতিটি যখন একেবারেই বলা হয়নি তখন একাধিকবার বলা হয়েছিল। তারা সম্ভবত এটি এখনই ঠিক করে ফেলেছে - তবে আপনি যদি সেই বার্তাটি দেখতে পান তবে আপনি পদ্ধতিটি আসলে ডাকা হয়েছিল তা যাচাই করার বিষয়টি বিবেচনা করতে পারেন।

সম্পাদনা: এখানে সেই পরিস্থিতিতে এমন একাধিকবার যাচাই করার জন্য উদাহরণ দেওয়া হয়েছে যেখানে আপনি যাচাই করতে চান যে আপনি তালিকার প্রতিটি বস্তুর জন্য কোনও ফাংশন কল করেছেন (উদাহরণস্বরূপ)।

foreach (var item in myList)
  mockRepository.Verify(mr => mr.Update(
    It.Is<MyObject>(i => i.Id == item.Id && i.LastUpdated == item.LastUpdated),
    Times.Once());

সেটআপের জন্য একই পদ্ধতির ...

foreach (var item in myList) {
  var stuff = ... // some result specific to the item
  this.mockRepository
    .Setup(mr => mr.GetStuff(item.itemId))
    .Returns(stuff);
}

সুতরাং প্রতিবার গেটস্টফকে সেই আইটেম আইডের জন্য ডাকা হলে, এটি সেই আইটেমটির সাথে নির্দিষ্ট স্টাফ ফেরত দেবে। বিকল্পভাবে, আপনি এমন কোনও ফাংশন ব্যবহার করতে পারেন যা আইটেম আইডকে ইনপুট হিসাবে গ্রহণ করে এবং স্টাফ ফেরত দেয়।

this.mockRepository
    .Setup(mr => mr.GetStuff(It.IsAny<int>()))
    .Returns((int id) => SomeFunctionThatReturnsStuff(id));

অন্য একটি পদ্ধতি যা আমি কিছুক্ষণ আগে ব্লগে দেখেছি (ফিল হ্যাক সম্ভবত?) কোনও ধরণের অদ্ভুত বস্তু থেকে সেটআপ ফিরে আসছিল - প্রতিটি বার যখন ফাংশনটি বলা হয় তখন এটি একটি সারি থেকে কোনও আইটেম টানত।


1
ধন্যবাদ, এটি আমার কাছে বোধগম্য। আমি এখনও যা বুঝতে পারি না সেটি হ'ল সেটআপ বা যাচাইকরণে বিশদটি নির্দিষ্ট করতে হবে। এটা বেশ বিভ্রান্তিকর। এই মুহুর্তে, আমি কেবল সেটআপে যা কিছু অনুমতি দিচ্ছি এবং যাচাইয়ের মানগুলি উল্লেখ করছি।
লুইস মীরাবাল

যখন আপনি একাধিক কল আসেন তখন কীভাবে আমি বার্তাগুলি চেক করতে পারি? ক্লায়েন্ট বার্তা নেয় এবং একাধিক কুইয়েবল মেসেজ তৈরি করতে পারে, যা একাধিক কল এবং সেই কলগুলির প্রত্যেকটিতে শেষ হবে, আমাকে বিভিন্ন বার্তা চেক করতে হবে। আমি এখনও সাধারণভাবে ইউনিট পরীক্ষার সাথে লড়াই করছি, আমি এটির সাথে এখনও খুব বেশি পরিচিত নই।
লুইস মীরাবাল

আপনার কীভাবে এটি করা উচিত তা বিবেচনা করে আমার মনে হয় না যাদুর সিলভার বুলেট রয়েছে। এটি অনুশীলন নেয় এবং আপনি আরও ভাল হওয়া শুরু করেন। আমার জন্য, আমি কেবল তখনই প্যারামিটারগুলি নির্দিষ্ট করি যখন তাদের সাথে তুলনা করার মতো কিছু আছে এবং যখন আমি ইতিমধ্যে অন্য পরীক্ষায় সেই পরামিতিটি পরীক্ষা করছি না। একাধিক কল হিসাবে বিভিন্ন পন্থা আছে। একাধিকবার ডাকা এমন ফাংশনটি স্থাপন ও যাচাই করার জন্য, আমি সাধারণত প্রতিটি কলের জন্য সেটআপ কল করি বা যাচাই করি (টাইমস.অনস ()) - প্রায়শই লুপ জন্য with প্রতিটি কলকে আলাদা করতে আপনি নির্দিষ্ট পরামিতি ব্যবহার করতে পারেন।
মেয়ো

আমি একাধিক কলের জন্য কয়েকটি উদাহরণ যুক্ত করেছি - উপরে উত্তর দেখুন।
মেয়ো

1
"এছাড়াও, মোক সহ একটি বাগ সম্পর্কে সচেতন থাকুন যেখানে ত্রুটি বার্তায় বলা হয়েছে যে পদ্ধতিটি যখন একেবারেই বলা হয়নি তখন একাধিকবার বলা হয়েছিল They তারা এখনই এটি ঠিক করে ফেলেছিল - তবে আপনি যদি সেই বার্তাটি দেখতে পান তবে আপনি যাচাই করার বিষয়টি বিবেচনা করতে পারেন পদ্ধতিটি আসলে বলা হত। " - এর মতো একটি বাগ একটি উপহাসের লাইব্রেরি আইএমএইচওকে সম্পূর্ণরূপে অবৈধ করে দেয়। এটির জন্য তাদের যথাযথ পরীক্ষার কোডটি
কীভাবে মজাদার

20

একটি সহজ উপায় হ'ল:

ObjectA.Verify(
    a => a.Execute(
        It.Is<Params>(p => p.Id == 7)
    )
);

আমি এই কাজটি পেয়ে যাচ্ছি বলে মনে হচ্ছে না, আমি যাচাই করার চেষ্টা করছি যে আমার পদ্ধতিটি কোডের সাথে ডেকে আনা হয়েছিল R তবে আমার পরীক্ষাটি সর্বদা পাস হয়, যদিও প্যারামিটারটি পাস হয় ডাব্লুআরডিডি .. m.Setup(x => x.CreateSR(Code.WRDD)).ReturnsAsync(0); await ClassUnderTest.CompleteCC(accountKey, It.IsAny<int>(), mockRequest); m.Verify(x => x.CreateSR(It.Is<Code>(p => p == Code.WRCC)), Times.Once());
গ্রেগ কুইন

1

আমি বিশ্বাস করি যে ম্যাক সাম্যতা যাচাই করবে এই সমস্যাটিতে। এবং, যেহেতু এক্সএমএলমেন্ট ইক্যুয়ালগুলিকে ওভাররাইড করে না, তাই এটি বাস্তবায়ন রেফারেন্সের সমতার জন্য পরীক্ষা করবে।

আপনি কি একটি কাস্টম অবজেক্ট ব্যবহার করতে পারবেন না, তাই আপনি সমানকে ওভাররাইড করতে পারেন?


হ্যাঁ, আমি এটা করে শেষ করেছি। আমি বুঝতে পেরেছিলাম যে সমস্যাটি XML পরীক্ষা করছে checking প্রশ্নের দ্বিতীয় অংশে আমি একটি বস্তুর সাথে এক্সএমএলকে ডিসেরায়ালাইজিংয়ের একটি সম্ভাব্য উত্তর যুক্ত করেছি
লুইস মিরাবাল

1

এগুলির মধ্যে একটিও ছিল, তবে ক্রিয়াটির পরামিতিটি কোনও সার্বজনীন সম্পত্তি ছাড়াই একটি ইন্টারফেস ছিল। পৃথক পদ্ধতিতে It.Is () ব্যবহার করে শেষ হয়েছিল এবং এই পদ্ধতির মধ্যে ইন্টারফেসের কিছু উপহাস করতে হয়েছিল

public interface IQuery
{
    IQuery SetSomeFields(string info);
}

void DoSomeQuerying(Action<IQuery> queryThing);

mockedObject.Setup(m => m.DoSomeQuerying(It.Is<Action<IQuery>>(q => MyCheckingMethod(q)));

private bool MyCheckingMethod(Action<IQuery> queryAction)
{
    var mockQuery = new Mock<IQuery>();
    mockQuery.Setup(m => m.SetSomeFields(It.Is<string>(s => s.MeetsSomeCondition())
    queryAction.Invoke(mockQuery.Object);
    mockQuery.Verify(m => m.SetSomeFields(It.Is<string>(s => s.MeetsSomeCondition(), Times.Once)
    return true
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.