Utilizzare Spring nelle web application – parte 4

Logo_Spring_252x150Finalmente si scrive del codice, dirà qualcuno… La fase di analisi e configurazione in effetti è stata un po’ lunga (ben tre articoli), anche se rispetto ad un progetto reale abbiamo davvero bruciato molte tappe. In questo appuntamento inizieremo a realizzare in maniera agile il progetto; il metodo che utilizzeremo non è l’unico e probabilmente nemmeno il migliore, ma ha il grande pregio di lasciare poco spazio al caso e consente di avere un’applicazione funzionante (e corretta) in poco tempo. Al lavoro, dunque!

Ancora configurazioni…

Prima di procedere dobbiamo aggiungere, ancora una volta, delle dipendenze al file pom.xml; la sezione <dependencies> avrà ora questo contenuto:

<dependencies>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
    <scope>compile</scope>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>opensymphony</groupId>
    <artifactId>sitemesh</artifactId>
    <version>2.4.2</version>
  </dependency>

  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.1</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
    <scope>test</scope>
  </dependency>

</dependencies>

Preparazione dei test

Procederemo ora alla scrittura del test JUnit; è prassi comune di tutte le pratiche agili infatti scrivere i test prima dell’implementazione, in questo modo si hanno diversi vantaggi, fra i quali ne citiamo un paio di significativi:

  • il codice viene utilizzato subito, questo facilita l’individuazione di eventuali problemi o difficoltà nell’utilizzo;
  • si stabilisce da subito una definizione di “funzionante”, rimuovendo molte incomprensioni fra clienti, sviluppatori e tester.

Per tutti i test che necessitano di accedere all’application context di Spring utilizzeremo una nostra specializzazione di AbstractJUnit4SpringContextTests, una classe messa a disposizione da Spring che consente di caricare a runtime un application context e di mantenerlo in memoria durante l’esecuzione dei test, velocizzando di molto l’esecuzione degli stessi. La nostra classe dunque si chiamerà AbstractTest, il cui sorgente deve essere memorizzato in src/test/java/it/artera/springtut/AbstractTest.java:

La classe come vedete è apparentemente vuota, in realtà quello che ci interessa è l’annotazione @ContextConfiguration, che indica al runtime dove cercare la configurazione dell’applicazione.

Il modello

Per il momento il modello dei dati dell’applicazione sarà costituito da una semplice classe, Insertion, che conterrà i dati di un’inserzione:

package it.artera.springtut;

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@ContextConfiguration(locations = "classpath:applicationContext.xml")
public abstract class AbstractTest extends AbstractJUnit4SpringContextTests {
}

(La realizzazione dei metodi setter e getter è stata omessa per per motivi di spazio).

La homepage

Nel secondo articolo della serie abbiamo stilato un elenco delle user stories, una di queste era appunto la Homepage. Riassumendo, vorremmo queste caratteristiche:

  • indirizzo: pagina di default, ovvero “/” oppure “/index.html”;
  • elenco delle inserzioni più recenti.

Il controller per la homepage si chiamerà IndexController, ma prima di implementarlo creiamo il relativo test in src/test/java/it/artera/springtut/controller/IndexControllerTest.java

package it.artera.springtut.controller;

import static org.junit.Assert.*;
import it.artera.springtut.AbstractTest;
import it.artera.springtut.model.Insertion;

import java.util.List;
import java.util.Map;

import org.junit.Test;

public class IndexControllerTest extends AbstractTest {

    @Test
    public void test_execute() {
        IndexController ctl = (IndexController) applicationContext.getBean("indexController");

        Map<String, Object> data = ctl.execute();
        assertNotNull(data);
        List<Insertion> insertionsList = (List<Insertion>) data.get("insertionsList");
        assertNotNull(insertionsList);
        assertTrue(insertionsList.size() > 0);
    }

}

Il test verifica che il controller restituisca, dalla chiamata al metodo execute(), una mappa contenente un oggetto “insertionsList”, e che questo oggetto sia una lista non vuota di inserzioni; lo si può eseguire sia da un IDE come Eclipse o Netbeans (attenzione ad utilizzare la modalità “JUnit 4” e non “Junit 3”) oppure da linea di comando:

mvn test -Dtest=IndexControllerTest

Purtroppo per noi però il test fallirà, per il semplice motivo che il controller… non esiste ancora!

Sviluppi

Nel prossimo articolo implementeremo il controller e il primo service, sempre mantenendo il nostro approccio test-driven.

AGGIORNAMENTO (7/4/2011)

Il file pom.xml dell’articolo in origine conteneva un errore: la dipendenza corretta da configurare è javax.servlet:servlet-api:2.5 e non javax:javaee-api:6.0-SNAPSHOT. Il file pom.xml corretto è quindi quello riportato qui sopra.

Linkografia