FTP, электронная почта и т.д может Вы тестировать с эмуляцией сервера. Это трудно, но возможно.
Не тестируемый некоторая обработка ошибок. В каждом коде существует обработка ошибок, которая никогда не может происходить. Например, в Java должна быть выгода многие исключение, потому что это - часть интерфейса. Но используемый экземпляр никогда не будет бросать его. Или случай по умолчанию переключателя, если для всех возможных случаев блок случая существует.
, Конечно, часть не нужной обработки ошибок может быть удалена. Но есть ли ошибка кодирования в будущем тогда, это плохо.
Вызов remove для коллекции во время итерации по ней будет вызывать исключение ConcurrentModificationException каждый раз, даже если все это делается в одном потоке - правильная вещь для этого нужно получить явный итератор и вызвать .remove () для этого.
Изменить: изменить ваш пример:
Iterator<Map.Entry<GenericEvent, Command>> i = eventMultiMap.entries().iterator();
while (i.hasNext()) {
if (i.next().getValue().equals(command)) {
i.remove();
nbRemoved++;
}
}
Если другой поток может изменить вашу мульти-карту во время работы этой логики, вам нужно будет добавить синхронизированный блок в код MHarris:
synchronized (eventMultimap) {
Iterator<Entry<GenericEvent, Command>> i = eventMultiMap.entries.iterator();
while (i.hasNext()) {
if (i.next().getValue().equals(command)) {
i.remove();
nbRemoved++;
}
}
}
Или вы можете опустить итератор как следует,
synchronized (eventMultimap) {
int oldSize = eventMultimap.size();
eventMultimap.values().removeAll(Collections.singleton(command));
nbRemoved = oldSize - eventMultimap.size();
}
Вызов removeAll () не требует синхронизации. Однако, если вы опустите синхронизированный блок, multimap может мутировать между вызовом removeAll () и одним из вызовов size (), что приведет к неправильному значению nbRemoved.
Теперь, если ваш код однопоточный, и вы просто хотите избежать вызова ConcurrentModificationException, вы можете опустить Multimaps.synchronizedMultimap и синхронизированную логику (eventMultimap).
synchronized (eventMultimap) {
int oldSize = eventMultimap.size();
eventMultimap.values().removeAll(Collections.singleton(command));
nbRemoved = oldSize - eventMultimap.size();
}
Вызов removeAll () не требует синхронизации. Однако, если вы опустите синхронизированный блок, multimap может мутировать между вызовом removeAll () и одним из вызовов size (), что приведет к неправильному значению nbRemoved.
Теперь, если ваш код однопоточный, и вы просто хотите избежать вызова ConcurrentModificationException, вы можете опустить Multimaps.synchronizedMultimap и синхронизированную логику (eventMultimap).
synchronized (eventMultimap) {
int oldSize = eventMultimap.size();
eventMultimap.values().removeAll(Collections.singleton(command));
nbRemoved = oldSize - eventMultimap.size();
}
Вызов removeAll () не требует синхронизации. Однако, если вы опустите синхронизированный блок, multimap может мутировать между вызовом removeAll () и одним из вызовов size (), что приведет к неправильному значению nbRemoved.
Теперь, если ваш код однопоточный, и вы просто хотите избежать вызова ConcurrentModificationException, вы можете опустить Multimaps.synchronizedMultimap и синхронизированную логику (eventMultimap).
Вы можете увидеть этот блогпост для другой подводной ловушки, уступая ConsurrentModificationException
при прохождении MultiMAP, без другого мешающего потока. Короче говоря, если вы проходите клавиши MultiMap, доступ к соответствующей коллекции значений, связанных с каждым ключом, и удалить некоторый элемент из такого собрания, , если этот элемент оказывается последним из коллекции , вы собираетесь иметь ConsurrentModificationException
Когда вы пытаетесь получить доступ к следующему ключу - потому что опорожнение коллекции вызывает удаление клавиши, таким образом, структурно изменение ключей MultiMap.