代码之家  ›  专栏  ›  技术社区  ›  Feelsbadman

如何对具有使用数据库连接的方法的类进行单元测试?

  •  0
  • Feelsbadman  · 技术社区  · 6 年前

    我试着在一个 controller 类,它至少有一个方法在内部使用 DAO 从 DB (MySQL) .

    我遇到的问题是dao方法给出了空值,最后 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
    
        }
    }
    

    配置.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 回复  |  直到 6 年前
        1
  •  1
  •   Å imon Kocúrek    6 年前

    而不是嘲笑 config ,嘲笑 Dao . 因为模拟配置没有设置 @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"));
    }
    
        2
  •  0
  •   Michel Foucault    6 年前

    DAO对象必须在单元测试中模拟。 Here