1

I've begun learning unit tests. I'm trying to write some tests using Junit5 and Mockito for my DAO's. And I need help, what next I need. How should I test it ?

import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class RecipeDao {

    private static final String CREATE_RECIPE_QUERY = "INSERT INTO " +
            "recipe(name, ingredients, description, created, preparation_time, preparation, admin_id)" +
            "VALUES (?,?,?,?,?,?,?)";
   
    /**
     * Create recipe
     *
     * @param recipe object
     * @return created Recipe in db
     */
    public Recipe create(Recipe recipe) {
        try (Connection connection = DbUtil.getConnection();
             PreparedStatement statement = connection.prepareStatement(CREATE_RECIPE_QUERY,
                     PreparedStatement.RETURN_GENERATED_KEYS)
        ) {
            statement.setString(1, recipe.getName());
            statement.setString(2, recipe.getIngredients());
            statement.setString(3, recipe.getDescription());
            statement.setString(4, currentTime());
            statement.setInt(5, recipe.getPreparationTime());
            statement.setString(6, recipe.getPreparation());
            statement.setInt(7,recipe.getAdminId());

            int result = statement.executeUpdate();

            if (result != 1) {
                throw new RuntimeException("Execute update returned " + result);
            }

            try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
                if (generatedKeys.first()) {
                    recipe.setId(generatedKeys.getInt(1));
                    return recipe;
                } else {
                    throw new RuntimeException("Generated key was not found");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

I write class DbUtil to connecting in database.


import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class DbUtil {
    private static DataSource dataSource;

    public static Connection getConnection() throws SQLException {
        return getInstance().getConnection();
    }

    private static DataSource getInstance() {
        if (dataSource == null) {
            try {
                Context context = new InitialContext();
                dataSource = (DataSource) context.lookup("java:comp/env/jdbc/scrumlab");
            } catch (NamingException e) {
                e.printStackTrace();
            }
        }
        return dataSource;
    }
}

I don't know how prepare connection to database used Mockito. I tried as below. But I don't know if I'm using @Mock correctly.

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.internal.util.reflection.Fields;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;

import javax.sql.DataSource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
class RecipeDaoTest {

    @InjectMocks
    private RecipeDao recipeDao;

    @Mock
    DataSource mockDataSource;

    @Mock
    Connection mockConn;

    @Mock
    PreparedStatement mockPreparedStmnt;

    @Mock
    ResultSet mockResultSet;


    public RecipeDaoTest() {
    }

    @BeforeEach
    void setUp() throws SQLException {
        when(mockDataSource.getConnection()).thenReturn(mockConn);
        when(mockDataSource.getConnection(anyString(), anyString())).thenReturn(mockConn);
        doNothing().when(mockConn).commit();
        when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);
        doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
        when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
        when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
        when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);

    }

    @org.junit.jupiter.api.Test
    void create() {
    }
}

Is it correct way to test it?

mszyba
  • 96
  • 1
  • 11
  • Welcome to SO. This isn't a discussion forum or tutorial. Please take the [tour](https://stackoverflow.com/tour) and take the time to read [How to Ask](https://stackoverflow.com/help/how-to-ask) and the other links found on that page. Ask concrete questions about an implementation problem, not about concepts such as Unit-Tests in general. – sschmid Mar 10 '21 at 16:55
  • I think it is useless to unit test a dao. Test it with an embedded database (like h2 or hsqldb) or with https://www.testcontainers.org/. See here maybe : https://stackoverflow.com/questions/9807414/dao-unit-testing – fego Mar 10 '21 at 17:08
  • @Schmidt thank typu for your help and tour. It's my first post here, as you saw. I have never use unit test, but I want to use finally. The dao class isn't a good first class to test, I think. – mszyba Mar 10 '21 at 17:48

0 Answers0