Я пишу приложение iOS, используя MonoTouch, у которого есть много информации для ввода на нескольких разных экранах. Информацию A, B и C можно ввести на экране 1, но мне нужно отобразить Info B на экране 3 вместе со входами для информации X, Y, Z и т. Д. Пользователь может перейти от экрана 1 к экрану 7, а затем вернуться к экрану 3.Как тестировать классы интеграции/интеграции, основанные на NSNotificationCenter (в MonoTouch)?
Итак, я создал статический класс для получения всей информации (через NSNotifications) и ее кеширования. Он также прослушивает запросы на получение информации (опять же через NSNotifications) с различных экранов, упаковывает соответствующую информацию (в частных статических методах) из кеша и отправляет другое уведомление в ответ. Этот класс должен всегда иметь актуальную информацию и поэтому должен соответствовать любому экрану, к которому пользователь переходит.
public static class InformationFlowController
{
static List<NSObject> _observers;
static Dictionary<SomeEnum, Object> _data;
static InformationFlowController()
{
_observers = new List<NSObject>();
_data = new Dictionary<SomeEnum, Object>();
_observers.Add(NSNotificationCenter.DefaultCenter.AddObserver(Notifications.PayloadA, HandlePayloadA));
...
_observers.Add(NSNotificationCenter.DefaultCenter.AddObserver(Notifications.RequestA, HandleRequestA));
}
// receive information A
static void HandlePayloadA(NSNotification ntf)
{
var infoA = (InfoA)ntf.Object;
if (A == null) { /* throw an exception */ }
if (_data.ContainsKey(EnumA))
{
_data.Remove(EnumA);
}
_data.Add(EnumA, infoA);
}
// receive request for info A
static void HandleRequestA(NSNotification ntf)
{
InfoA info = null;
if (_data.ContainsKey(EnumA))
{
info = _data.GetValue(EnumA);
}
// its up to the receiver what it wants to do if it gets null
NSNotificationCenter.DefaultCenter.PostNotificationName(Notifications.ResponseA, info);
}
}
Все это прекрасно работает.
Мой вопрос: как я могу его интегрировать/интегрировать? Из-за природы приложения/политики/yadda-yadda у меня должно быть покрытие на 100%. Вот что я пробовал и с чем сталкивался.
Проблема, которую я имею пытаюсь написать интеграционный тест для этого является обеспечение того, если сделать запрос для информации, что я получаю ответ с информацией А.
[Test]
public void HandleRequestForATest()
{
// setup the data in the IFC here
NSNotificationCenter.DefaultCenter.AddObserver(Notifications.ResponseA, delegate(NSNotification ntf)
{
var info = ntf.Object as InfoA;
Assert.IsNotNull(info, "Info is null!");
// some other asserts to check the data within info
}
NSNotificationCenter.DefaultCenter.PostNotificationName(Notifications.RequestA, null);
}
Испытание проходит с 0 утверждает , Я поставил точку останова на var info = ntf.Object as InfoA;
, и она никогда не трогается. Я подумал, может быть, его получение GC'd, прежде чем он сможет получить ответ, но я поставил точку останова в методе IFC.HandleRequestA
, и он никогда не будет вызван. Через проверку я вижу, что уведомления регистрируются в Центре по умолчанию, но они, похоже, не увольняются.
В дополнение ко всему этому, как я могу проверить, чтобы уведомление было получено в течение определенного промежутка времени, а если нет, пропустите тест? Я пытался добавить переменную класса:
bool assertsCompleted = false;
и модификации теста:
[Test]
public void HandleRequestForATest()
{
// setup the data in the IFC here
NSNotificationCenter.DefaultCenter.AddObserver(Notifications.ResponseA, delegate(NSNotification ntf)
{
var info = ntf.Object as InfoA;
Assert.IsNotNull(info, "Info is null!");
// some other asserts to check the data within info
assertsCompleted = true;
}
NSNotificationCenter.DefaultCenter.PostNotificationName(Notifications.RequestA, null);
NSTimer.CreateTimer(2, delegate
{
if (!assertsCompleted)
{
Assert.IsTrue(false, "Notification not received or Asserts not complete!");
}
}
}
я поставил точку останова на if (!assertsCompleted)
и не получить удар либо.
Пожалуйста, помогите! :)
EDIT2 Я изменил класс МОК от статических к нестатическому (а также методам), и что решено проблема с обработчиками не вызываются. Это означает, что я должен был создать его в AppDelegate и TestFixtureSetUp, но я думаю, что мы сможем жить с этим. /EDIT2
(http://stackoverflow.com/q/ 4373079/639445) – miek