Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Básico de Testing en Java

Curso Básico de Testing en Java

Ferran Maylinch Carrasco

Ferran Maylinch Carrasco

Test de integración con base de datos: guardar películas y búsqueda de películas individuales

20/24
Recursos

Por el momento, nuestras pruebas están cargando varias veces la información de la base de datos y vamos a solucionar este problema creando una función que borre la información. Para esto, debemos usar la instrucción @After para que JUnit ejecute la función cada vez que termina de hacer un test.

Aportes 15

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

En este caso puede ser util la anotación @BeforeClass en lugar del @Before, para que no estés creando y cerrando conexiones con cada uno de los tests sino que lo hagas por cada clase de Tests, te ahorras bastante en términos de máquina. Sin embargo, el @BeforeClass debe ir con un método estático.

Más info al respecto

Me ha pasado algo curioso con el orden de los test porque cuando ejecutaba uno iba mal porque primero insertaba la película del test y luego en el otro test de traer todas las películas fallaba porque faltaba una. Para corregirlo pueden utilizar una anotación llamada @Order(<Order number>) en el que indican explícitamente el orden de sus tests

package com.mael.javatests.movies.data;

import com.mael.javatests.movies.model.Genre;
import com.mael.javatests.movies.model.Movie;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.ScriptUtils;

import javax.sql.DataSource;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;

public class MovieRepositoryImplTest {

    private static MovieRepositoryImpl movieRepository;

    @BeforeClass
    public static void setUp() throws Exception {
        //Creando una base de datos de prueba en memoria con h2
        DataSource dataSource = new DriverManagerDataSource("jdbc:h2:mem:test;MODE=MYSQL", "sa", "sa");
        //Ejecuto script para crear tabla de movies y unos datos de prueba
        ScriptUtils.executeSqlScript(dataSource.getConnection(), new ClassPathResource("sql-scripts/test-data.sql"));
        //creo una clase JDBC template para enviarsela a mi repositorio de Movie
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        movieRepository = new MovieRepositoryImpl(jdbcTemplate);
    }

    @Test
    @Order(1)
    public void insertMovie() {
        Movie movie = new Movie("Super 8", 112, Genre.THRILLER);
        movieRepository.saveOrUpdate(movie);
        Movie movieExpected = movieRepository.findById(4L);
        assertThat(movieExpected, is(new Movie(4,"Super 8", 112, Genre.THRILLER)));
    }

    @Test
    @Order(2)
    public void loadAllMovies() throws SQLException {
        Collection<Movie> movies = movieRepository.findAll();
        assertThat(movies, is(Arrays.asList(
                new Movie(1, "Dark Knight", 152, Genre.ACTION),
                new Movie(2, "Memento", 113, Genre.THRILLER),
                new Movie(3, "Matrix", 136, Genre.ACTION),
                new Movie(4,"Super 8", 112, Genre.THRILLER)
        )));
    }

    @Test
    @Order(3)
    public void loadMovieById() {
        Movie movie = movieRepository.findById(2L);
        assertThat(movie, is(new Movie(2, "Memento", 113, Genre.THRILLER)));
    }
}

Si a alguien le dice que está deprecado el queryForObject aquí:

jdbcTemplate.queryForObject("select * from movies where id = ?", args, movieMapper);

Es porque ahora los dos últimos parámetros van invertidos, así:

jdbcTemplate.queryForObject("select * from movies where id = ?", movieMapper, args );

Fuente

No encontré la forma de realizar “shutdown” en la base de datos. 😢

No era mas sencillo hacer una unión con el curso de Spring?

En vez de usar @After podríamos usar @BeforeClass para que el método donde se carga la base de datos solo se ejecute una vez antes de empezar a probar todos los test

MovieRepositoryJdbc.java

package com.platzi.javatests.movies.data;

import com.platzi.javatests.movies.model.Genre;
import com.platzi.javatests.movies.model.Movie;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.Collection;

public class MovieRepositoryJdbc implements MovieRepository {

  private JdbcTemplate jdbcTemplate;
  private static RowMapper<Movie> movieMapper = (rs, rowNum) ->
    new Movie(
      rs.getInt("id"),
      rs.getString("name"),
      rs.getInt("minutes"),
      Genre.valueOf(rs.getString("genre"))
    );

  public MovieRepositoryJdbc(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }

  @Override
  public Movie findById(long id) {
    Object[] args = { id };
    return jdbcTemplate.queryForObject("SELECT * FROM movies WHERE id = ?", args, movieMapper);
  }

  @Override
  public Collection<Movie> findAll() {
    return jdbcTemplate.query("SELECT * FROM movies", movieMapper);
  }

  @Override
  public void saveOrUpdate(Movie movie) {
    jdbcTemplate.
      update(
        "INSERT INTO movies(name, minutes, genre) VALUES(?, ?, ?)",
        movie.getName(),
        movie.getMinutes(),
        movie.getGenre().toString()
      );
  }
}

MovieRepositoryIntegrationTest.java

package com.platzi.javatests.movies.data;

import com.platzi.javatests.movies.model.Movie;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.ScriptUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collection;

import static com.platzi.javatests.movies.model.Genre.ACTION;
import static com.platzi.javatests.movies.model.Genre.THRILLER;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

@RunWith(MockitoJUnitRunner.class)
public class MovieRepositoryIntegrationTest {

  @InjectMocks
  private MovieRepositoryJdbc movieRepository;

  @Mock
  private JdbcTemplate jdbcTemplate;

  private DataSource dataSource;

  @Before
  public void setUp() throws SQLException {
    dataSource = new DriverManagerDataSource("jdbc:h2:mem:test;MODE=MYSQL", "sa", "sa");
    jdbcTemplate = new JdbcTemplate(dataSource);
    movieRepository = new MovieRepositoryJdbc(jdbcTemplate);

    ScriptUtils.executeSqlScript(dataSource.getConnection(), new ClassPathResource("sql-scripts/test-data.sql"));
  }

  @After
  public void tearDown() throws Exception {
    final Statement s = dataSource.getConnection().createStatement();
    s.execute("DROP ALL objects DELETE files");
  }

  @Test
  public void loadAllMovies() {
    Collection<Movie> movies = movieRepository.findAll();

    assertThat(movies, is(Arrays.asList(
        new Movie(1, "Dark Knight", 152, ACTION),
        new Movie(2, "Memento", 113, THRILLER),
        new Movie(3, "Matrix", 136, ACTION)
    )));
  }

  @Test
  public void loadMovieById() {
    Movie movie = movieRepository.findById(2);

    assertThat(movie, is(new Movie(2, "Memento", 113, THRILLER)));
  }

  @Test
  public void insertAMovie() {
    Movie movie = new Movie("Super 8", 112, THRILLER);
    movieRepository.saveOrUpdate(movie);
    Movie movieSavedInDB = movieRepository.findById(4);

    assertThat(movieSavedInDB, is(new Movie(4, "Super 8", 112, THRILLER)));
  }
}

Igual se podría agregar el id a nuestro objeto movie, para no tener que hacer otro de nuevo en el assert

    @Test
    public void insertAMovie() {
        Movie movie = new Movie("Super 8", 112, Genre.THRILLER);
        movieRepository.saveOrUpdate(movie);

        Movie movieFromDb = movieRepository.findById(4);
        movie.setId(4);

        assertEquals(movie, movieFromDb);
    }

Pésimo curso la verdad :u, no he entendido nada utiliza JDBC, Spring cosas que no he visto siguiendo la ruta de Java, además de que el profesor programa super rápido, no lo recomiendo tomar

En el momento que se indico el valor del id=4, en la línea de:
Movie movie = new Movie(4, “Super 8”, 112, Genre.THRILLER);

es porque se está utilizando el mismo objeto para insertarlo en la BD y se está utilizando en la comparación.

Muchas gracias por explicarnos los pasos para hacer los test de este proyecto, a continuación, comparto los resultados del que hice:
   

Bueno ya que tuve problemas con el video anterior, debo esperar me respondan para hacer este y lo que sigue.

Todo bien por aca 😃 gracias

Solo el alcance que vi en comentarios más abajo… el Genre debe ser String 😃

😃 Great!!!