Objectivos

  • Realização de testes de software mais sofisticados utilizando a biblioteca jmockit.

Documentação

Exercício


Considere a seguinte classe Bookstore, a qual tem um método getBookTitle que recebe o ISBN de um livro e devolve o título do livro caso existe ou devolve null caso o ISBN não represente nenhum livro. A concretização deste método depende da classe BookstoreService. O método de procura de um livro desta classe lança a excepção BookNotFounfException devolve a referência null quando não encontra um livro com o ISBN dado. Para os testes que se querem realizar não é importante o código da classe BookstoreService. O que se pretende testar é que a classe Bookstore tem o comportamento correcto e que interage com a classe BookstoreService da forma esperada. A forma como os testes vão ser realizados têm a vantagem de não exigir que a classe BookstoreService esteja totalmente concretizada (permitindo assim o desenvolvimento em paralelo das duas classes) ou de executar o código de BookstoreService (o que pode ser vantajoso em situações em que a execução deste código tenha um custo alto, seja em tempo de execução seja em termos de inicialização do estado em que a instância desta classe terá que estar).

Pretende-se testar a classe Bookstore utilizando as bibliotecas de testes JUnit e jmockit, realize uma bateria de caso de testes que verificam que a classe Bookstore tem o comportamento esperado independentemente da concretização da classe BookstoreService (embora assumindo que esta tem o comportamento correcto).

O objectivo dos casos de testes a concretizar é que a classe Bookstore tem o comportamento esperado. Nomeadamente, quer-se verificar que:

  1. A classe Bookstore recorre sempre a BookstoreService para encontrar o título do livro dado um ISBN. 
  2. A situação de sucesso é tratada correctamente (o título devolvido por Bookstore é o igual ao devolvido por BookstoreService).
  3. A situação de insucesso é tratada correctamente, e neste caso corresponde a devolver o valor null.

Dado seguinte código destas classes

e o seguinte ficheiro pom.xml para projectos Java já com a dependência para a framework JUnit incluída, crie um projecto que utilize a biblioteca jmockit e faça a bateria de testes descrita. A dependência para o jmockit é a seguinte:

<dependency> 
   <groupId>org.jmockit</groupId> 
   <artifactId>jmockit</artifactId>
   <version>1.16</version> 
   <scope>test</scope>
</dependency>

Atenção, devido a uma dependência da biblioteca jmoclkit, a declaração da dependência da biblioteca jmockit no ficheiro pom.xml tem que anteceder a declaração da dependência da framework JUnit. Caso isto não seja feito, a execução dos casos de teste que utilizem a biblioteca jmockit falharão e apresentarão o seguinte erro:

  • JMockit wasn't properly initialized; please ensure that jmockit precedes junit in the runtime classpath, or use @RunWith(JMockit.class)
Tenha agora em consideração as seguintes alterações no comportamento destas classes:
  • A classe Bookstore passa a lançar a excepção BookNotFoundException sempre que BookstoreService não encontra um título para o livro pretendido.
  • A procura de livros pode estar indisponível (por exemplo, a base de dados com a informação dos livros não está disponível). Para representar este caso, a classe BookstoreService utiliza a excepção DatabaseAccessException. A classe Bookstore trata esta situação, apanhando esta excepção e convertendo-a numa excepção de mais alto nível ServiceUnavailableException.

Actualize os ficheiros Bookstore.java e BookstoreService.java correspondentes às entidades Bookstore e BookstoreService e adicione as novas excepções DatabaseAccessException, ServiceUnavailableException e BookNotFoundException (ServiceUnavailableException.javaBookNotFoundException.java e DatabaseException.java) e actualize a classe de teste para exercitar o novo comportamento.

Considere agora uma nova versão da classe Bookstore que pretende ter uma maior disponibilidade de serviço, utilizando duas instâncias distintas da classe BookstoreService (idealmente ligadas a duas bases de dados localizadas em computadores diferentes), em que a segunda é utilizada apenas quando a primeira está inacessível. Considerando agora a nova versão desta classe, altere a classe de teste para ter em conta este novo requisito. Por forma a poder-se verificar um comportamento específico para cada instância de BookstoreService, é necessário acrescentar um construtor à classe Bookstore que nos permitirá criar estas instâncias no casos de teste em que isso seja necessário:
public BookstoreFT(BookstoreService service, BookstoreService anotherService) {
    this.primary = service;
    this.secondary = anotherService;
}


Esta nova versão fica definida no ficheiro BookstoreFT.java. Crie uma nova classe de teste que exercita agora esta nova versão de Bookstore.