2015-07-21 3 views
0

У меня есть объект, который после получения некоторых сообщений изменяется асинхронно (внутренний поток изменяет состояние). После изменения состояния я хочу проверить какое-то поведение.Проверить поведение параллельного кода

Поэтому в основном мне нужно сделать что-то вроде:

  1. Создать объект
  2. Отправить сообщение для объекта
  3. Дождитесь состояния, чтобы изменить
  4. поведение Тест

Однако, состояние частный и не подвергается.

Есть ли элегантное решение для этого, которое не требует раскрытия состояния?

А если нет - разумно ли потребовать изменения основного кода, чтобы сделать его более проверяемым?

+0

Возможно, есть элегантный способ сигнализировать изменение состояния через поведение. Это помогло бы, если бы вы могли уточнить поведение, которое вы надеетесь испытать. Сколько возможных действий вы ожидаете? Например, будет ли это только то, что объект возвращает 0 до изменения состояния и 1 после? – NBartley

+0

Фактическое протестированное поведение не имеет значения. Дело в том, что его можно тестировать только после изменения состояния, иначе тест не имеет смысла. – traveh

ответ

-1

Если государство является закрытым, оно доступно только в пределах его собственного класса (https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html), что означает, что вы не сможете получить состояние из только что созданного объекта без изменения класса.
Теперь, разумно ли это изменить класс для того, чтобы сделать некоторые испытания до нескольких факторов:

  • Сколько людей работают над этим кодом?
  • Сколько людей уже использует предыдущую версию этого кода?
  • Проблемы с целостностью, с которыми вам придется столкнуться, если вы измените переменную состояния на общедоступную и добавите метод геттера.
  • т.д.

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

-1

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

Foo bar = new Foo(); 
    bar.setValue(true); 

    Field field = Foo.class.getDeclaredField("value"); 
    field.setAccessible(true); 
    Object value = field.get(bar); 

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

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

+0

Я хорошо знаю, что есть варианты для уродливых решений. Мой вопрос был, если есть * элегантное решение *, а не уродливое ... – traveh

+0

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

+0

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

1

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

final Waiter waiter = new Waiter(); 

bus.registerMessageHandler(message -> { 
    waiter.assertEquals(message.body(), "foo"); 
    waiter.resume(); 
}); 

waiter.await(5000); 

Этот тест создает официанта, который ждет в течение 5 секунд. Обратный вызов, зарегистрированный на шине сообщений, будет выполнять утверждение в отдельном потоке до возобновления официанта, чтобы тест мог завершиться.

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