Как выполнить модульное тестирование класса, у которого есть методы, использующие соединение с базой данных? - PullRequest
1 голос
/ 05 апреля 2020

Я пытаюсь запустить тесты для класса controller, и у него есть хотя бы метод, который внутренне использует DAO для извлечения информации из DB (MySQL).

У меня проблема в том, что дао метод дает ноль, и я получаю ошибку NullPointerException.

Как проверить класс, в котором есть методы, которые внутренне используют соединение с базой данных?
Не было смог найти любой полезный пост / ответ.

Структура проекта:

src
    main
        java
            [package]
                RegisterController.java
                Config.java // configuration class
    test
        java
            [package]
                RegisterControllerTest.java

RegisterController. java

package com.webapp.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.webapp.Config;
import com.webapp.dao.AccountDao;

@Controller
public class RegisterController {

    @Autowired
    AccountDao accDao;


    public String validateUsername(String uname){
        List<String> errors = new ArrayList<String>();

        // ... unrelated code 

        // NullPointerException thrown here
        if(accDao.getAccountByUsername(uname) != null)
            errors.add("err#taken");

        return errors.toString();
    }
}

RegisterControllerTest. java

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;

import com.webapp.controller.RegisterController;
import com.webapp.Config;

@SpringBootTest
public class RegisterControllerTest {

    @Mock
    private Config config;

    private RegisterController rc;

    @BeforeEach
    public void init() {
        config = Mockito.mock(Config.class);
        rc = new RegisterController();
    }


    @Test
    public void testValidateUsername() {
        assertEquals("[]", rc.validateUsername("Username123")); // N.P.E

    }
}

Config. java пакет com.webapp;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import com.webapp.dao.AccountDao;
import com.webapp.dao.AccountDaoImpl;
import com.webapp.dao.Dao;

@Configuration
@ComponentScan(basePackages = { "com.webapp.controller", "com.webapp.dao", "com.webapp.test" })
public class Config {

    private static class Database {
        private static String host = "127.0.0.1";
        private static String user = "root";
        private static String pass = "root";
        private static String dbname = "memedb";
        private static int port = 3306;

        public static String getUrl() {
            return "jdbc:mysql://"+host+":"+port+"/"+dbname+"?serverTimezone=Europe/Stockholm";
        }
    }

    @Bean
    public DriverManagerDataSource getDataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl(Database.getUrl());
        ds.setUsername(Database.user);
        ds.setPassword(Database.pass);
        return ds;
    }


    @Bean
    public AccountDao getAccDao() {
        return new AccountDaoImpl(getDataSource());
    }

}

Ответы [ 2 ]

1 голос
/ 05 апреля 2020

Вместо насмешек config, издевайтесь над Dao. Вы получаете NPE, потому что макет конфигурации не устанавливает @Autowired accDao ... поэтому ваш accDao == null:

@Controller
public class RegisterController {

    AccountDao accDao;

    public RegisterController(AccountDao accDao) {
      this.accDao = accDao;
    }

    ...
}
@BeforeEach
public void init() {
  accDaoMock = Mockito.mock(AccountDao.class);
  rc = new RegisterController(accDaoMock);
}

@Test
public void testValidateUsername() {
  when(accDaoMock.getAccountByUsername("Username123")).thenReturn(null);
  assertEquals("[]", rc.validateUsername("Username123"));
}
0 голосов
/ 05 апреля 2020

Почему вы конфигурируете БД подключения программно? Советую настроить подключение БД с автоконфигурацией Spring Boot.

Объект DAO должен имитировать в модульном тесте. Здесь - хорошая статья о тесте Junit для приложения Spring Boot.

...