2013-03-09 3 views
0

Я тестирую метод, который генерирует два разных исключения. Это мой заголовок:JAVA: JUnitTest, метод тестирования, который выбрасывает два исключения

@Test (expected = A8InvalidInputException.class)
public void testGuessCharacter() throws A8InvalidInputException, A8AlreadyGuessedException { ... }

Тело имеет две попытки/уловы блоки (поиск по SO привел к сообщению, что сказал, что, как вы проверить, что исключения выбрасываются), один для каждого исключения , Мне кажется, я должен разбить это на два метода тестирования, особенно потому, что у меня есть только один ожидаемый атрибут. Однако, когда я это делаю, метод, который должен тестировать A8InvalidInputException, требует try/catch для A8AlreadyGuessedException, а метод, который должен тестировать A8AlreadyGuessedException, требует try/catch для исключения A8InvalidInputException. Я не уверен, как написать этот тест. Это метод, который я пытаюсь проверить:

/** 
* This method returns whether a specified character exists in the keyPhrase field 
* @param guess a character being checked for in the keyPhrase field 
* @return returns whether a specified character exists in the keyPhrase field 
* @throws A8InvalidInputException if a non-valid character is passed as input to this method 
* @throws A8AlreadyGuessedException if a valid character which has already been guessed is passed as input to this method 
*/ 
public boolean guessCharacter(char guess) throws A8InvalidInputException, A8AlreadyGuessedException 
{ 
    if(isValidCharacter(guess)) 
    { 
     guess = Character.toLowerCase(guess); 

     if(guessedCharacters.contains(guess)) 
     { 
      throw new A8AlreadyGuessedException("" + guess); 
     } 
     else 
     { 
      guessedCharacters.add(guess); 
      if(keyPhrase.contains("" + guess)) 
       return true; 
      else 
      { 
       numberOfGuessesLeft--; 
       return false; 
      } 
     }  
    } 
    else 
    { 
     throw new A8InvalidInputException("" + guess); 
    } 
} 
+0

Метод слишком длинный в любом случае. –

+0

Дейв, мой инструктор предоставил его. Я этого не писал.Помимо этого, я думал, что 30 строк были принятыми в отрасли макс в соответствии с руководством по кодированию Java/руководством по стилю. – speedracer

+0

«Принимаемые в промышленности макс?» Никогда не слышал об этом. Что еще более важно, он имеет достаточно высокую циклическую сложность, чтобы заставить меня дергаться: условные выражения слишком глубоко вложены, чтобы позволить удобные рассуждения, и есть вложенные, где ни один не требуется. Дублированная логика, потому что есть символ, когда все остальное ожидает строку. Простое выравнивание (примерно https://gist.github.com/davelnewton/258761cbf3143da4288c) решает эту проблему. Правильный рефакторинг делает тестирование настолько тривиальным, что почти смешно. –

ответ

4

Метод может бросить только одно исключение, когда оно запущено. Вот почему может быть только один ожидаемый атрибут.

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

Не ставьте инструкцию try/catch в свои методы @Test, просто объявляйте, что они генерируют исключения.

+0

Этьен, ладно, это имеет смысл, но что вы имеете в виду, просто заявляете, что они бросают исключения? На этой неделе я просто узнал об JUnitTesting, так что пока это не совсем понятно для меня. Благодарю. – speedracer

+0

Я имел в виду поместить 'throws A8InvalidInputException, A8AlreadyGuessedException' в заголовок метода тестирования, но теперь я вижу, что вы это сделали. Итак, зачем вам нужны блоки try/catch в теле? –

+0

Я видел [сообщение] (http://stackoverflow.com/questions/785618/in-java-how-can-i-validate-a-thrown-exception-with-junit) на SO, в котором указаны блоки try/catch были способом добиться этого. В противном случае я не уверен, как написать тест. – speedracer

2

Да, вы должны разбить это на два модульных теста. Один с недопустимым вводом для запуска A8InvalidInputException, а другой с «уже угаданным» входом для запуска A8AlreadyGuessedException.

6

Просто добавьте оба исключения в бросках положение:

@Test (expected = A8InvalidCharacterException.class) 
public void testInvalidCharacterScenario() throws A8InvalidInputException, A8AlreadyGuessedException { ... } 

@Test (expected = A8InvalidInputException.class) 
public void testInvalidInputScenario() throws A8InvalidInputException, A8AlreadyGuessedException { ... } 

Затем, если один тест бросает исключение (другое непредвиденное один), то ваш тест будет автоматически потерпеть неудачу.

1

Рассмотрите, чтобы сделать ваши тесты немного проще, разбив их на две отдельные части - тестирование isValidCharacter и тестирование guessCharacter отдельно.

Предполагая, что isValidCharacter(guess) потерпит неудачу, если вы получите недопустимое предположение, я думаю, что метание A8InvalidInputException в этом методе было бы идеальным.

public boolean isValidCharacter(char guess) throws A8InvalidInputException { 
    // have your logic to check the guess, and if it's invalid, throw 
} 

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

@Test (expected = A8InvalidInputException.class) 
public void testIsValidCharacterWithInvalidCharacter() { 
    // write your test here. 
} 

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

И, наконец, вы будете касаться только тестов для guessCharacter вокруг того, выбрасывает ли он A8AlreadyGuessedException.

@Test (expected = A8AlreadyGuessedException.class) 
public void testGuessCharacterWithAlreadyGuessedValue() { 
    // write your test here. 
} 
+0

Макото, спасибо, но я не могу изменить исходный код. Мой инструктор предоставил его. Я также написал бы здесь отдельные методы (возможно, проверяя обоснованность, прежде чем передавать его как аргумент?), Поскольку я думал, что метод должен только что-то сделать, но, эй, я студент. Что я знаю? – speedracer

+1

Ну, методы могут делать много вещей, но когда вы тестируете, вы должны только проверять одно. Я по-прежнему твердо придерживаюсь мнения, что 'isValidCharacter' должен вызывать исключение, поскольку это единственная часть кода, которая отвечает за утверждение недопустимого ввода. Опять же, речь идет об ограничении площади поверхности, на которую вы должны попасть с помощью теста, - это упрощает процесс написания тестов и производит менее хрупкие тесты. – Makoto