c# গঠন মোক দিয়ে প্রথম এবং দ্বিতীয়বার ভিন্ন ভিন্ন মূল্য ফেরত দেয়




জাহিদ হাসানের নাটক (6)

একটি কলব্যাক যোগ করা আমার জন্য কাজ করে না, পরিবর্তে আমি এই পদ্ধতিটি ব্যবহার করেছি http://haacked.com/archive/2009/09/29/moq-sequences.aspx এবং আমি এই রকম পরীক্ষা দিয়ে শেষ হলাম:

    [TestCase("~/page/myaction")]
    [TestCase("~/page/myaction/")]
    public void Page_With_Custom_Action(string virtualUrl) {

        // Arrange
        var pathData = new Mock<IPathData>();
        var pageModel = new Mock<IPageModel>();
        var repository = new Mock<IPageRepository>();
        var mapper = new Mock<IControllerMapper>();
        var container = new Mock<IContainer>();

        container.Setup(x => x.GetInstance<IPageRepository>()).Returns(repository.Object);
        repository.Setup(x => x.GetPageByUrl<IPageModel>(virtualUrl)).ReturnsInOrder(null, pageModel.Object);

        pathData.Setup(x => x.Action).Returns("myaction");
        pathData.Setup(x => x.Controller).Returns("page");

        var resolver = new DashboardPathResolver(pathData.Object, repository.Object, mapper.Object, container.Object);

        // Act
        var data = resolver.ResolvePath(virtualUrl);

        // Assert
        Assert.NotNull(data);
        Assert.AreEqual("myaction", data.Action);
        Assert.AreEqual("page", data.Controller);
    }

আমি এই মত একটি পরীক্ষা আছে:

    [TestCase("~/page/myaction")]
    public void Page_With_Custom_Action(string path) {
        // Arrange
        var pathData = new Mock<IPathData>();
        var pageModel = new Mock<IPageModel>();
        var repository = new Mock<IPageRepository>();
        var mapper = new Mock<IControllerMapper>();
        var container = new Mock<IContainer>();

        container.Setup(x => x.GetInstance<IPageRepository>()).Returns(repository.Object);

        repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(() => pageModel.Object);

        pathData.Setup(x => x.Action).Returns("myaction");
        pathData.Setup(x => x.Controller).Returns("page");

        var resolver = new DashboardPathResolver(pathData.Object, repository.Object, mapper.Object, container.Object);

        // Act
        var data = resolver.ResolvePath(path);

        // Assert
        Assert.NotNull(data);
        Assert.AreEqual("myaction", data.Action);
        Assert.AreEqual("page", data.Controller);
    }

GetPageByUrl আমার ড্যাশবোর্ডপথ্রেভারভারে দুবার রান করে, কিভাবে আমি মোককে প্রথমবার এবং পৃষ্ঠা মডলকে ফিরতে বলব? দ্বিতীয়টি মেনে চলবে?


গৃহীত উত্তর , পাশাপাশি SetupSequence উত্তর , হ্যান্ডলগুলি ফিরে স্টেশন ।

Returns() এর কিছু কার্যকর ওভারলোড রয়েছে যেখানে আপনি ম্যাকড পদ্ধতিতে প্রেরিত পরামিতিগুলির উপর ভিত্তি করে একটি মান প্রদান করতে পারেন। গৃহীত উত্তর প্রদত্ত http://haacked.com/archive/2009/09/29/moq-sequences.aspx উপর ভিত্তি করে, ওভারলোডের জন্য এখানে আরেকটি এক্সটেনশান পদ্ধতি রয়েছে।

public static class MoqExtensions
{
    public static IReturnsResult<TMock> ReturnsInOrder<TMock, TResult, T1>(this ISetup<TMock, TResult> setup, params Func<T1, TResult>[] valueFunctions)
        where TMock : class
    {
        var queue = new Queue<Func<T1, TResult>>(valueFunctions);
        return setup.Returns<T1>(arg => queue.Dequeue()(arg));
    }
}

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

repository
    .Setup(x => x.GetPageByUrl<IPageModel>(path))
    .ReturnsInOrder(new Func<string, IPageModel>[]
        {
            p => null, // Here, the return value can depend on the path parameter
            p => pageModel.Object,
        });

প্রয়োজন হলে একাধিক পরামিতি ( T2 , T3 , ইত্যাদি) সহ এক্সটেনশন পদ্ধতির জন্য ওভারলোড তৈরি করুন।


মোক এর সর্বশেষ সংস্করণ (4.2.1312.16২২) দিয়ে, আপনি সেটআপসুইভেশন ব্যবহার করে ইভেন্টগুলির একটি ক্রম সেটআপ করতে পারেন। এখানে একটি উদাহরণ:

_mockClient.SetupSequence(m => m.Connect(It.IsAny<String>(), It.IsAny<int>(), It.IsAny<int>()))
        .Throws(new SocketException())
        .Throws(new SocketException())
        .Returns(true)
        .Throws(new SocketException())
        .Returns(true);

কলিং সংযোগ শুধুমাত্র তৃতীয় এবং পঞ্চম প্রচেষ্টা সফল হবে অন্যথায় একটি ব্যতিক্রম নিক্ষেপ করা হবে।

তাই আপনার উদাহরণের জন্য এটি এমন কিছু হবে:

repository.SetupSequence(x => x.GetPageByUrl<IPageModel>(virtualUrl))
.Returns(null)
.Returns(pageModel.Object);

বিদ্যমান উত্তরগুলি দুর্দান্ত, কিন্তু আমি ভাবলাম যে আমি আমার বিকল্পটি নিক্ষেপ করব যা System.Collections.Generic.Queue ব্যবহার করে। System.Collections.Generic.Queue এবং System.Collections.Generic.Queue ফ্রেমওয়ার্কের কোন বিশেষ জ্ঞান দরকার না - যেহেতু আমি এটি লেখার সময় আমার কাছে কিছু ছিল না ! :)

var pageModel = new Mock<IPageModel>();
IPageModel pageModelNull = null;
var pageModels = new Queue<IPageModel>();
pageModels.Enqueue(pageModelNull);
pageModels.Enqueue(pageModel.Object);

তারপর ...

repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(pageModels.Dequeue);

সামান্য ভিন্ন প্রয়োজন সঙ্গে একই ধরনের সমস্যার জন্য এখানে পৌঁছেছেন।
আমাকে বিভিন্ন ইনপুট মানগুলির ভিত্তিতে মক থেকে বিভিন্ন ফিরতি মানগুলি পেতে এবং সমাধানটি পাওয়া যায় যা IMO আরও পাঠযোগ্য হিসাবে এটি মোক এর ঘোষণামূলক সিনট্যাক্স (লিঙ্কগুলিতে মক) ব্যবহার করে।

public interface IDataAccess
{
   DbValue GetFromDb(int accountId);  
}

var dataAccessMock = Mock.Of<IDataAccess>
(da => da.GetFromDb(It.Is<int>(acctId => acctId == 0)) == new Account { AccountStatus = AccountStatus.None }
&& da.GetFromDb(It.Is<int>(acctId => acctId == 1)) == new DbValue { AccountStatus = AccountStatus.InActive }
&& da.GetFromDb(It.Is<int>(acctId => acctId == 2)) == new DbValue { AccountStatus = AccountStatus.Deleted });

var result1 = dataAccessMock.GetFromDb(0); // returns DbValue of "None" AccountStatus
var result2 = dataAccessMock.GetFromDb(1); // returns DbValue of "InActive"   AccountStatus
var result3 = dataAccessMock.GetFromDb(2); // returns DbValue of "Deleted" AccountStatus

আপনার mock বস্তুর সেট আপ করার সময় আপনি একটি কলব্যাক ব্যবহার করতে পারেন। মোক উইকি থেকে উদাহরণ দেখুন ( http://code.google.com/p/moq/wiki/QuickStart )।

// returning different values on each invocation
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
    .Returns(() => calls)
    .Callback(() => calls++);
// returns 0 on first invocation, 1 on the next, and so on
Console.WriteLine(mock.Object.GetCountThing());

আপনার সেটআপ এইরকম দেখতে পারে:

var pageObject = pageModel.Object;
repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(() => pageObject).Callback(() =>
            {
                // assign new value for second call
                pageObject = new PageModel();
            });




moq