Rhino Mocks: переназначить новый результат для метода на заглушке - PullRequest
2 голосов
/ 23 сентября 2008

Я знаю, что могу сделать это:

IDateTimeFactory dtf = MockRepository.GenerateStub<IDateTimeFactory>();
dtf.Now = new DateTime();
DoStuff(dtf); // dtf.Now can be called arbitrary number of times, will always return the same value
dtf.Now = new DateTime()+new TimeSpan(0,1,0);  // 1 minute later
DoStuff(dtf); //ditto from above

Что, если вместо IDateTimeFactory.Now быть свойством, это метод IDateTimeFactory.GetNow () , как мне сделать то же самое?

Согласно предложению Иуды ниже, я переписал свой вспомогательный метод SetDateTime следующим образом:

    private void SetDateTime(DateTime dt) {
        Expect.Call(_now_factory.GetNow()).Repeat.Any();
        LastCall.Do((Func<DateTime>)delegate() { return dt; });
    }

, но все равно выдает «Результат для ICurrentDateTimeFactory.GetNow (); уже настроен». ошибки.

Плюс, он все еще не будет работать с заглушкой ....

Ответы [ 4 ]

6 голосов
/ 05 февраля 2011

Я знаю, что это старый вопрос, но думал, что выложу обновление для более свежих версий Rhino Mocks.

Исходя из предыдущих ответов, в которых используется Do (), при использовании AAA в Rhino Mocks (доступно из версии 3.5+) доступен слегка более чистый (IMO) способ.

.
    [Test]
    public void TestDoStuff()
    {
        var now = DateTime.Now;
        var dtf = MockRepository.GenerateStub<IDateTimeFactory>();
        dtf
           .Stub(x => x.GetNow())
           .Return(default(DateTime)) //need to set a dummy return value
           .WhenCalled(x => x.ReturnValue = now); //close over the now variable

        DoStuff(dtf); // dtf.Now can be called arbitrary number of times, will always return the same value
        now = now + new TimeSpan(0, 1, 0); // 1 minute later
        DoStuff(dtf); //ditto from above
    }

    private void DoStuff(IDateTimeFactory dtf)
    {
        Console.WriteLine(dtf.GetNow());
    }
1 голос
/ 24 сентября 2008

Джордж,

Используя ваш обновленный код, я получил это на работу:

MockRepository mocks = new MockRepository();

[Test]
public void Test()
{
    IDateTimeFactory dtf = mocks.DynamicMock<IDateTimeFactory>();

    DateTime desiredNowTime = DateTime.Now;
    using (mocks.Record())
    {
        SetupResult.For(dtf.GetNow()).Do((Func<DateTime>)delegate { return desiredNowTime; });
    }
    using (mocks.Playback())
    {
        DoStuff(dtf); // Prints the current time    
        desiredNowTime += TimeSpan.FromMinutes(1);  // 1 minute later    
        DoStuff(dtf); // Prints the time 1 minute from now
    }
}

void DoStuff(IDateTimeFactory factory)
{
    DateTime time = factory.GetNow();
    Console.WriteLine(time);
}

FWIW, я не верю, что вы можете сделать это с помощью заглушек; вместо этого вам нужно использовать макет.

0 голосов
/ 24 сентября 2008

Хорошо, мой первый ответ не сработает, потому что GetSomething может вызываться несколько раз, а вы не знаете, сколько раз.

Вы попадаете в какой-то сложный сценарий - неизвестное количество вызовов методов, но с разными результатами после вызова DoSomething - я рекомендую разбить ваш модульный тест, чтобы быть проще, или вам придется пройти модульные тесты для ваших юнит-тестов. : -)

В противном случае, вот как вы можете выполнить то, что вы пытаетесь сделать:

bool shouldReturnABC = true;
using (mocks.Record())
{
   Expect.Call(s.GetSomething()).Repeat.Any();

   LastCall.Do((Func<string>)delegate()
   {
      return shouldReturnABC ? "ABC" : "XYZ";
   }
}
using (mocks.Playback())
{
   DoStuff(s);
   shouldReturnABC = false;
   DoStuff(s);
}
0 голосов
/ 24 сентября 2008

Вы можете использовать Expect.Call для достижения этой цели. Вот пример использования модели записи / воспроизведения:

using (mocks.Record())
{
   Expect.Call(s.GetSomething()).Return("ABC"); // 1st call will return ABC
   Expect.Call(s.GetSomething()).Return("XYZ"); // 2nd call will return XYZ
}
using (mocks.Playback())
{
   DoStuff(s);
   DoStuff(s);
}
...