Действительно ли это - плохой дизайн?

Может быть, IsNullOrWhiteSpace это метод, который вы ищете? http://msdn.microsoft.com/en-us/library/system.string.isnullorwhitespace.aspx

5
задан Kenneth Cochran 10 June 2009 в 16:06
поделиться

7 ответов

При разработке сверху вниз довольно часто обнаруживается, что вы используете множество имитаторов. Нужных вам частей нет, поэтому, естественно, вам нужно издеваться над ними. С учетом сказанного, это действительно похоже на тест на приемочный уровень. По моему опыту, BDD или Контекст / Спецификация начинает становиться немного странным на уровне модульного тестирования. На уровне модульного тестирования я бы, вероятно, сделал что-то большее, вроде ...

when_adding_an_account
   should_use_account_service_to_create_new_account
   should_update_screen_with_new_account_details

Возможно, вы захотите пересмотреть свое использование интерфейса для IAccount. Я лично придерживаюсь с сохранением интерфейсов для сервисов над объектами домена. Но это больше личное предпочтение.

Несколько других небольших предложений ...

  • Возможно, вы захотите рассмотреть возможность использования фреймворка Mocking, такого как Rhino Mocks (или Moq), который позволяет вам избегать использования строк для ваших утверждений.

  _mockAccountService.Expect(mock => mock.Create())
     .Return(_account);

  • Если вы работаете в стиле BDD, я видел один распространенный шаблон - использование связанных классов для настройки тестирования. В вашем примере ...
public class MainPresenterSpec 
{
    // Protected variables for Mocks 

    [SetUp]
    public void Setup()
    {
       // Setup Mocks
    }

}

[TestFixture]
public class WhenUserAddsAccount : MainPresenterSpec
{
    [Test]
    public void ShouldCreateNewAccount()
    {
    }
}
  • Также я бы порекомендовал изменить ваш код, чтобы использовать условие защиты.
     public void AddAccount()
     {
        if (AccountService.AccountTypes.Count != 1)
        {
            // Do whatever you want here.  throw a message?
        return;
        }

    IAccount account = AccountService.Create();

        _view.Accounts.Add(account);
     }
3
ответ дан 14 December 2019 в 08:58
поделиться

Тестирование жизнеобеспечения будет намного проще, если вы используете контейнер автоматического имитации, такой как RhinoAutoMocker (часть StructureMap ). Вы используете контейнер auto mocking для создания тестируемого класса и запрашиваете у него зависимости, необходимые для теста (ов). Контейнеру может потребоваться ввести 20 элементов в конструктор, но если вам нужно протестировать только одно, вам нужно только запросить его.

using StructureMap.AutoMocking;

namespace Foo.Business.UnitTests
{
    public class MainPresenterTests
    {
        public class When_asked_to_add_an_account
        {
            private IAccountService _accountService;
            private IAccount _account;
            private MainPresenter _mainPresenter;

            [SetUp]
            public void BeforeEachTest()
            {
                var mocker = new RhinoAutoMocker<MainPresenter>();
                _mainPresenter = mocker.ClassUnderTest;
                _accountService = mocker.Get<IAccountService>();
                _account = MockRepository.GenerateStub<IAccount>();
            }

            [TearDown]
            public void AfterEachTest()
            {
                _accountService.VerifyAllExpectations();
            }

            [Test]
            public void Should_use_the_AccountService_to_create_an_account()
            {
                _accountService.Expect(x => x.Create()).Return(_account);
                _mainPresenter.AddAccount();
            }
        }
    }
}

Структурно я предпочитаю использовать подчеркивания между словами вместо RunningThemAllTogether, так как мне легче сканировать. Я также создаю внешний класс с именем тестируемого класса и несколько внутренних классов с именем тестируемого метода. Затем методы тестирования позволяют указать поведение тестируемого метода. При запуске в NUnit это дает вам контекст вроде:

Foo.Business.UnitTests.MainPresenterTest
  When_asked_to_add_an_account
    Should_use_the_AccountService_to_create_an_account
    Should_add_the_Account_to_the_View
2
ответ дан 14 December 2019 в 08:58
поделиться

Это похоже на правильное количество имитаторов для докладчика со службой, которая должна вернуть учетную запись.

Это больше похоже на приемочный тест, чем на модульный тест, хотя - возможно, если вы уменьшите сложность утверждения, вы обнаружите, что высмеивается меньший набор проблем.

1
ответ дан 14 December 2019 в 08:58
поделиться

Да, ваш дизайн ошибочен. Вы используете mocks :)

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

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

Если у вас чистые интерфейсы, я не спорю с реализацией простого интерфейса, который имитирует (или mocks) нереализованный интерфейс с другим модулем. Эту симуляцию можно использовать так же, как насмешку,

1
ответ дан 14 December 2019 в 08:58
поделиться

Я считаю, что если вам нужны моки, ваш дизайн неверен.

Компоненты должны быть многоуровневыми. Вы создаете и тестируете компоненты A изолированно. Затем вы создаете и тестируете B + A. В случае успеха вы создаете слой C и тестируете C + B + A.

В вашем случае вам не понадобится "_mockAccountService". Если ваш реальный AccountService был протестирован, просто используйте его. Таким образом, вы будете знать, что любые ошибки есть в MainPresentor, а не в самом макете.

Если ваш реальный AccountService не был протестирован, остановитесь. Вернитесь и сделайте то, что вам нужно, чтобы убедиться, что он работает правильно. Доведите его до такой степени, чтобы на него действительно можно было положиться, и тогда макет вам не понадобится.

0
ответ дан 14 December 2019 в 08:58
поделиться

Возможно, вы захотите использовать MockContainers , чтобы избавиться от всего фиктивного управления при создании презентатора. Это значительно упрощает модульные тесты.

0
ответ дан 14 December 2019 в 08:58
поделиться

Это нормально, но я бы ожидал, что где-то там будет контейнер для автозапуска IoC. Код намекает на то, что автор теста вручную (явно) переключается между имитируемыми и реальными объектами в тестах, чего не должно быть, потому что, если мы говорим о тесте unit (где unit представляет собой только один класс), это проще просто автоматически смоделировать все остальные классы и использовать макеты.

Я пытаюсь сказать, что если у вас есть тестовый класс, который использует как mainView , так и mockMainView , у вас нет модульного теста в строгом смысле этого слова - больше похоже на интеграционный тест.

0
ответ дан 14 December 2019 в 08:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: