Работа с DependencyObjects в модульных тестах Silverlight - PullRequest
3 голосов
/ 17 апреля 2009

Я уже некоторое время пишу модульные тесты с использованием NUnit и Moq с моим кодом Silverlight. Одна проблема, с которой я продолжаю сталкиваться, связана с DependencyObjects.

Если что-то получено из DependencyObject, я не могу создать его экземпляр в своем тесте. Например, MouseEventArgs является производным от DependencyObject. Если у меня есть код, который принимает эти аргументы, я не могу создать эти аргументы по нескольким причинам ... одна из них заключается в том, что это DependencyObject.

Насколько я понимаю, базовый конструктор DependencyObject пытается работать с некоторыми статическими данными, которые не существуют, пока вся система Silverlight не запущена и работает. Любая конструкция класса, производная от DependencyObject, генерирует исключение. Облом.

Я не использую Silverlight Unit Test Framework , потому что он действительно не является модульным тестированием и требует пользовательского интерфейса. Мне нужны настоящие, безголовые юнит-тесты.

В любом случае, лучшее, что я придумал, - это обернуть эти объекты и дать им интерфейсы, такие как ITimelineMarker, и я даю им методы расширения для этого: timelineMarker.ToInterface(). Это хорошо работает, и я могу издеваться над ними ... но мне было интересно:

Кто-нибудь придумал лучший способ иметь дело с объектами DepencencyOb в модульных тестах Silverlight?

Ответы [ 4 ]

3 голосов
/ 12 мая 2009

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

Ваш пользовательский интерфейс действительно должен иметь дело только с событиями пользовательского интерфейса и передавать какую-либо обработку другому слою, единственное, что остается проверить в вашем пользовательском интерфейсе, это графические ответы (например, когда вы нажимаете кнопку, панель скользит из сторона), и единственный хороший способ проверить подобные взаимодействия - это нажать кнопку.

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

0 голосов
/ 06 мая 2009

Я вижу, что DependencyObject в абстрактном классе.

Бесстыдно отрываясь от насмешек Rhino Документация , представьте, что у вас есть абстрактный класс:

public abstract class MessageBase {
   private List<User> _receivers = new List<User>();
   public void Send() {
      //Some setup
      DetermineReceivers();
      SendMessages();
   }
   private void SendMessages() {
      //Lots of logic
   }
   protected abstract void DetermineReceivers();
   protected void AddReceiver(Group g) {
      //Lots of logic <---- Test this
   }
}

и вы хотите проверить указанную часть. Тогда вы создадите фальшивый класс, который вы можете смутить:

TestFixture
public sealed class MessageBaseTester {
 public abstract class MockMessageMocker
 {
    public abstract List<Group> RecipientsGroups { get; set; }
 }
 private class MockMessage : MessageBase {
   private MockMessageMocker _mock;
   public MockMessage(MockMessageMocker mock) {
      _mock = mock;
   }
   protected override void DetermineReceivers() {
      if (_mock.RecipientsGroups != null)
         foreach(Group g in _mock.RecipientsGroups)
            base.AddReceiver(g);
   }
 }
}

После этого ваш тест может выполнить следующее:

 Test
 public void ShouldblablablaWhenBlabla() {
    var SuThelper = mocks.Stub();
    var SuT = new MockMessage(SuThelper);
    using (mocks.Record())
    {
       Expect.Call(SuTHelper.RecipientsGroups).Return(
             new List<Group>{ new Group(...) });
    }
    using (mocks.Playback())
    {
       SuT.Send();
    }
 }

Вышеупомянутое решение имеет преимущество перед вашим в том, что вам не нужно изменять исходный код. Однако вам нужно написать некоторый «дополнительный» код, чтобы он работал.

0 голосов
/ 08 мая 2009

Попробуйте использовать SilverUnit для модульного тестирования Silverlight . Так как он подделывает инфраструктуру Silverlight, он может помочь с проблемными исключениями.

0 голосов
/ 23 апреля 2009

Вы смотрели проект TestDriven.NET Silverlight NUnit? Ссылка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...