Pegar uma exceção genérica em Java?

Usamos o JUnit 3 no trabalho e não há nenhuma anotação ExpectedException . Eu queria adicionar um utilitário ao nosso código para envolver isso:

  try { someCode(); fail("some error message"); } catch (SomeSpecificExceptionType ex) { } 

Então eu tentei isso:

 public static class ExpectedExceptionUtility { public static  void checkForExpectedException(String message, ExpectedExceptionBlock block) { try { block.exceptionThrowingCode(); fail(message); } catch (T ex) { } } } 

No entanto, o Java não pode usar tipos de exceção genéricos em um bloco catch, eu acho.

Como posso fazer algo assim, trabalhando em torno da limitação de Java?

Existe uma maneira de verificar se a variável ex é do tipo T ?

Você poderia passar o object Class e verificar isso de forma programática.

 public static  void checkForException(String message, Class exceptionType, ExpectedExceptionBlock block) { try { block.exceptionThrowingCode(); } catch (Exception ex) { if ( exceptionType.isInstance(ex) ) { return; } else { throw ex; //optional? } } fail(message); } //... checkForException("Expected an NPE", NullPointerException.class, //... 

Não tenho certeza se você gostaria de recolocar ou não; recomeçar seria igualmente falhar / errar o teste, mas semanticamente eu não faria, já que basicamente significa “nós não conseguimos a exceção que esperávamos” e isso representa um erro de programação, ao invés de um erro no ambiente de teste.

Eu entendo o impulso de tentar simplificar seu idioma de teste de exceção, mas sério: não. Cada escolha possível que você vai encontrar é uma cura que é pior do que a doença. Especialmente o absurdo @ExpectedException da JUnit 4! É uma solução de estrutura inteligente demais, exigindo que todos saibam como ela funciona, em oposição a um pouco evidente de código Java comum. Pior, isso não dá a você nenhuma maneira de envolver apenas a parte do seu teste que você espera lançar a exceção, então se uma etapa de instalação anterior lançar a mesma exceção, seu teste será aprovado mesmo que seu código esteja corrompido.

Eu poderia escrever uma longa diatribe sobre isso aqui (desculpe por não ter tido tempo suficiente para isso), já que tivemos uma longa discussão sobre essa questão entre os engenheiros de Java aqui no Google, e o consenso foi que nenhuma dessas soluções malucas valem a pena. Acostume-se a tentar / pegar, não é tão ruim assim.

Genéricos não são tipos. Eles não são modelos. Eles são verificações de tipo de tempo de compilation, em Java. Blocos de exceção capturam o tipo. Você pode pegar (Exception e) ou até pegar (Throwable e) e depois lançar conforme necessário.

Bem, você poderia simplesmente capturar Exception e recriar se não for uma Exceção esperada. Embora a boa prática de codificação geralmente determine que o caminho de sucesso do código não deve ser definido por uma Exceção, talvez você queira repensar seu design.

Você também pode usar um IDE que suporte template ao vivo (como o IntellJ IDEA por exemplo ) e atribuir um atalho como ee -> [tab] que insere o try / catch / ignore para o seu e permite que você digite o correto.

assim http://img80.imageshack.us/img80/433/capturadepantalla201006j.png

assim http://img641.imageshack.us/img641/6733/capturadepantalla201006w.png

A cláusula catch com o parâmetro type não é possível:
http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch