Pergunta

Eu estou escrevendo um teste para um pedaço de código que tem uma captura IOException nele que eu estou tentando tampa. O try / catch é algo como isto:

try {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
} catch (IOException e) {
    LOGGER.error("Bad news!", e);
} finally {

A maneira mais fácil parece fazer FileOutputStream lançar uma FileNotFoundException, mas talvez eu vou sobre isso todo o caminho errado.

Alguém aí tem alguma dica?

Foi útil?

Solução

Desde o seu comentário:

Sim, acho que a questão deve realmente ter sido "Como faço para criar um arquivo que não existe no Linux e Windows?" No Windows, eu posso usar 'New File ( "X: /")', onde X: é uma unidade letra que não existe. No Linux, isso não funciona, porque isso é uma nome válido de arquivo.

Olhe para java.io.File.createTempFile. Use-o para criar o arquivo e, em seguida, excluí-lo.

Provavelmente passá-lo algo como:

File tempFile;

tempFile = createTempFile(getClass().getName(), 
                          Long.toString(System.currentTimeMillis());
tempFile.delete();

Isso deve dar-lhe um nome exclusivo de uma maneira plataforma indendent que você pode usar com segurança, sem (muito) medo de TI existente.

Outras dicas

Você pode definir cacheFileName para um nome inválido ou para um que você sabe que não existe.

Há duas partes para qualquer teste: fazê-la acontecer e medição que você tem o resultado correto

.

injeção de falhas

A resposta mais fácil é aquele que já foi mencionado, que é definir cacheFileName para um arquivo que nunca vai existir. Isto é provavelmente a resposta mais prática nesta situação.

No entanto, para causar uma condição arbitrária como um IOException, o que você realmente quer é Fault Injection . Isso força falhas no seu código sem forçá-lo a instrumento de seu código-fonte. Aqui estão alguns métodos para fazer isso:

  • Mock objetos Você pode usar um método de fábrica para criar um ObjectOutputStream substituído ou FileOutputStream. No código de teste a implementação iria lançar uma IOException quando você queria, e na produção de código não iria modificar o comportamento normal.
  • Dependency Injection A fim de obter o seu objeto Mock no lugar certo, você poderia usar um quadro como Spring ou Seam 'inserir' o objeto apropriado para a classe que está fazendo a trabalhos. Você pode ver que estas estruturas têm mesmo uma prioridade para objetos que serão injetadas, para que durante a unidade de teste você pode substituir os objetos de produção com objetos de teste.
  • Aspect Oriented Programming Em vez de mudar a estrutura do seu código em tudo, você pode usar AOP para injetar a culpa no lugar certo. Por exemplo, usando AspectJ você poderia definir um pointcut onde você queria que a exceção seja lançada a partir de, e têm o Advice lançar a exceção desejada

Existem outras respostas para FALHA injeção em Java; por exemplo, um produto chamado AProbe foi pioneiro no que poderia ser chamado AOP em C há muito tempo, e eles também tem um produto Java.

Validação

Começar a exceção lançada é um bom começo, mas você também tem que validar que você tem o resultado certo. Assumindo que a amostra de código que você tem aí é correto, você deseja validar que tem iniciada essa exceção. Alguém acima indicado usando um objeto Mock para o seu logger, que é uma opção viável. Você também pode usar AOP aqui para pegar a chamada para o logger.

Presumo que o logger é log4j ; para resolver um problema semelhante, eu implementado minha própria appender log4j que capta log4j saída: eu especificamente capturar apenas ERROR e FATAL, que são susceptíveis de ser as mensagens de log interessantes em tal caso. O appender é referenciada em log4j.xml e é ativado durante o ensaio para a saída de log de erro de captura. Este é essencialmente um objeto fictício, mas eu não tive que reestruturar todo o meu código que tem um Logger log4j.

Eu estou escrevendo um teste para um pedaço de código que tem um captura IOException nele que eu estou tentando tampa.

Eu não sou inteiramente certo eu entendo o seu objetivo, mas se você quiser testar se a exceção é lançada, você pode dizer o teste você espera que ele lançar a exceção:

@Test(expected=IOException.class)

Seu teste será então falhar se a exceção não é lançada, e ter sucesso se for jogado (como, se o arquivo cacheFileName não existe).

A FileNotFoundException obviamente provocar a captura. O javadoc afirma os casos em que será lançada.

Você também deve considerar que o construtor ObjectOutputStream pode lançar uma IOException tão pode querer cobrir este caso em seus testes.

Duas maneiras fáceis seria ou cacheFileName conjunto para um arquivo inexistente ou definir o arquivo especificado para acesso somente leitura.

-John

Como o código está escrito, você poderia tentar ironizar a chamada de erro () no objeto LOGGER e verificar para ver se ele é chamado quando você espera uma IOException.

Seu desejo de teste pode ter descoberto um problema fundamental com o código como está escrito. Um erro está ocorrendo, mas não há nenhum valor booleano ou bandeira (definir o nome do arquivo para um padrão especial) que fornece outras seções do código para determinar se a escrita para o arquivo foi bem sucedida. Se isso está contido em uma função, talvez você poderia retornar um boolean ou definir uma variável de nível de objeto.

cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";

Claro que você poderia tomar medidas e saltar através de aros para programaticamente se certificar de que o nome do arquivo nunca, nunca, nunca existe, ou você pode usar uma String que nunca vai existir em 99,99999% dos casos.

Espero que isso é o que você quis dizer.

if(new File(cachedFile).exists()) {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
    //do your code here
} else {
    throw new FileNotFoundException("File doesn't exist!");
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top