Тестирование свойства, установленного для экземпляра нового объекта в Rhino Mocks 3.4.0 - PullRequest
1 голос
/ 10 октября 2019

Справочная информация

Я исправляю юнит-тесты, которые долгое время игнорировались для устаревшего кода в нашей организации. Они написаны с использованием Rhino Mocks 3.4.0, и я изо всех сил пытаюсь найти способ сделать этот тест успешным. Документация Rhino Mocks, похоже, ушла, и большинство ответов здесь и блоги, похоже, используют обновленный синтаксис 3.5 и 3.6.

Я настороженно отношусь к обновлению используемой нами версии Rhino Mocks, поскольку у нас есть несколькотысячи юнит-тестов, которые могут или не могут нуждаться в обновлении при обновлении.

Сценарий:

У нас есть Presenter и View. Когда Presenter инициализируется, он устанавливает некоторые свойства фильтра по умолчанию в представлении. В прошлом оба эти свойства были перечислениями, и испытание прошло. Последнее изменение обновило одно из свойств, чтобы оно стало экземпляром класса. Тест был обновлен для ожидания вызова статического метода, который создает экземпляр со значениями по умолчанию (соответствует тестируемому коду), но теперь тест завершается неудачно с ошибкой Rhino.Mocks.Exceptions.ExpectationViolationException: неупорядоченный вызов метода.

Пример кода:

    public enum FilterOptions { OptionA, OptionB, OptionC }

    public class OtherFilterOptions
    {
        public bool Filter1 { get; set;}
        public bool Filter2 { get; set; }

        public OtherFilterOptions(bool filter1 = true, bool filter2 = false)
        {
            Filter1 = filter1;
            Filter2 = filter2;
        }

        public static OtherFilterOptions DefaultFilterOptions()
        {
            return new OtherFilterOptions();
        }
    }

    public interface IToTestView
    {
        FilterOptions Property1 { set; }
        OtherFilterOptions Property2 { set; }
    }

    public class ToTestPresenter
    {
        public IToTestView View { get; set; }

        public ToTestPresenter(IToTestView view)
        {
            View = view;
        }

        public void InitialiseView()
        {
            View.Property1 = FilterOptions.OptionA;
            View.Property2 = OtherFilterOptions.DefaultFilterOptions();
        }
    }

И неудачный тест:

    [TestFixture]
    class Tests
    {
        [Test]
        public void TestOne()
        {
            var mocks = new MockRepository();
            var mockView = mocks.CreateMock<IToTestView>();

            ToTestPresenter presenter = new ToTestPresenter(mockView);
            using (mocks.Ordered())
            {
                mockView.Property1 = FilterOptions.OptionA;
                mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
            }

            mocks.ReplayAll();
            presenter.InitialiseView();
            mocks.VerifyAll();
        }
    }

Полная ошибка

Rhino.Mocks.Exceptions.ExpectationViolationException: Неупорядоченный вызов метода! Ожидаемый вызов: 'Ordered: {IToTestView.set_Property2 (RhinoMocksTestApp.OtherFilterOptions);} 'но было:' IToTestView.set_Property2 (RhinoMocksTestApp.OtherFilterOptions); '

Я предполагаю, что тест не пройден, поскольку устанавливаемое значение является вызовом метода, а не конкретным значением. Я попытался объявить переменную, используя mockView.Property2 = theVariable, но ошибка не изменилась.

Можно ли установить ожидание, что для Property2 будет установлено значение {некоторый объект со значениями Filter1 = true, Filter2 =ложный}? Я видел примеры, аналогично использующие Rhino Mocks 3.6, но доступно ли что-нибудь, использующее 3.4.0?

Редактировать: В качестве примера, это пример теста, который проходит в Rhino Mocks 3.6.1 - яв надежде найти синтаксис, который работает аналогично для 3.4.0, если он существует.

[Test]
public void TestOne()
{
    var mocks = new MockRepository();
    var mockView = MockRepository.GenerateMock<IToTestView>();
    ToTestPresenter presenter = new ToTestPresenter(mockView);

    mocks.ReplayAll();
    presenter.InitialiseView();

    mockView.AssertWasCalled(v => v.Property1 = FilterOptions.OptionA);
    mockView.AssertWasCalled(v => v.Property2 = Arg<OtherFilterOptions>.Matches(filters => 
        (filters.Filter1 == true) && (filters.Filter2 == false)));
}

1 Ответ

1 голос
/ 14 октября 2019

Ответ, который я искал, был в методе LastCall.Constraints (). Передача аргументов в Constraints позволяет указать значения свойств аргумента:

[Test]
public void TestOne()
{
    var mocks = new MockRepository();
    var mockView = mocks.CreateMock<IToTestView>();

    ToTestPresenter presenter = new ToTestPresenter(mockView);
    using (mocks.Ordered())
    {
         mockView.Property1 = FilterOptions.OptionA;
         mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
         LastCall.Constraints(
             Property.Value("Filter1", true)
             & Property.Value("Filter2", false));
    }

    mocks.ReplayAll();
    presenter.InitialiseView();
    mocks.VerifyAll();
}

Существует большое количество опций, которые можно передать в метод Constraints (). Подробная информация о некоторых из них на этой странице CodeProject

Другой вариант - LastCall.IgnoreArguments (), если вам все равно, какое свойство на самом деле установлено.

...