Java 迈巴蒂斯公司的Springboot公司';在使用Junit进行单元测试期间映射DateTime

Java 迈巴蒂斯公司的Springboot公司';在使用Junit进行单元测试期间映射DateTime,java,spring-boot,jackson,junit4,mybatis,Java,Spring Boot,Jackson,Junit4,Mybatis,我有以下DateTimeTypeHandler类: //Copyright 2012 Lucas Libraro // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // //

我有以下DateTimeTypeHandler类:

//Copyright 2012 Lucas Libraro
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
package com.common.mybatis.typehandler;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import java.sql.*;

@MappedTypes(DateTime.class)
public class DateTimeTypeHandler implements TypeHandler {

    /* (non-Javadoc)
     * @see org.apache.ibatis.type.TypeHandler#setParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType)
     */
    public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        if (parameter != null) {
            ps.setTimestamp(i, new Timestamp(((DateTime) parameter).getMillis()));
        } else {
            ps.setTimestamp(i, null);
        }
    }

    /* (non-Javadoc)
     * @see org.apache.ibatis.type.TypeHandler#getResult(java.sql.ResultSet, java.lang.String)
     */
    public Object getResult(ResultSet rs, String columnName) throws SQLException {
        Timestamp ts = rs.getTimestamp(columnName);
        if (ts != null) {
            return new DateTime(ts.getTime(), DateTimeZone.UTC);
        } else {
            return null;
        }
    }

    /* (non-Javadoc)
     * @see org.apache.ibatis.type.TypeHandler#getResult(java.sql.CallableStatement, int)
     */
    public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
        Timestamp ts = cs.getTimestamp(columnIndex);
        if (ts != null) {
            return new DateTime(ts.getTime(), DateTimeZone.UTC);
        } else {
            return null;
        }
    }

    /* (non-Javadoc)
     * @see org.apache.ibatis.type.TypeHandler#getResult(java.sql.ResultSet, int)
     */
    public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
        Timestamp ts = rs.getTimestamp(columnIndex);
        if (ts != null) {
            return new DateTime(ts.getTime(), DateTimeZone.UTC);
        } else {
            return null;
        }
    }
}
我能够使用以下bean将一些Java序列化为Json,Json序列化为Java:

数据库

package com.common.config;

import com.common.business.user.Employee;
import com.common.config.yaml.DatabaseConfig;
import com.common.mybatis.typehandler.DateTimeTypeHandler;
import com.commonTools.model.DBObject;
import com.commonTools.model.Snoop;
import com.commonTools.model.SnoopDBObject;
import org.apache.ibatis.type.TypeHandler;
import org.joda.time.DateTime;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

@Configuration
@Import(DatabaseConfig.class)
@MapperScan("com.persistence")
public class DataBean {

    @Autowired DatabaseConfig _databaseConfig;

    @Bean
    public DateTimeTypeHandler dateTimeTypeHandler(){
        return new DateTimeTypeHandler();
    }
    @Bean
    public SimpleDriverDataSource dataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriverClass(org.mariadb.jdbc.Driver.class);
        dataSource.setUsername(_databaseConfig.getUsername());
        dataSource.setPassword(_databaseConfig.getPassword());
        dataSource.setUrl(_databaseConfig.getUrl());
        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setTypeHandlers(new TypeHandler[] {
            new DateTimeTypeHandler(),
        });
        sessionFactory.setTypeAliases(new Class[] {
            DateTime.class,
            Employee.class,
            DBObject.class,
            Snoop.class,
            SnoopDBObject.class
        });
        return sessionFactory;
    }
}
package com.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonBean {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();


        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);

//      # TEST 0 (TODO: see result when activated using JodaTime)
        mapper.registerModule(new JodaModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS );
//      mapper.setDateFormat(new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ (z)"));

//      # TEST 1 (Res: fail sometimes when too much depth)
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // true default

//      # TEST 2 (Res: too much depth)
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
                .setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY)
                .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

        return mapper;
    }

}
JacksonBean

package com.common.config;

import com.common.business.user.Employee;
import com.common.config.yaml.DatabaseConfig;
import com.common.mybatis.typehandler.DateTimeTypeHandler;
import com.commonTools.model.DBObject;
import com.commonTools.model.Snoop;
import com.commonTools.model.SnoopDBObject;
import org.apache.ibatis.type.TypeHandler;
import org.joda.time.DateTime;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

@Configuration
@Import(DatabaseConfig.class)
@MapperScan("com.persistence")
public class DataBean {

    @Autowired DatabaseConfig _databaseConfig;

    @Bean
    public DateTimeTypeHandler dateTimeTypeHandler(){
        return new DateTimeTypeHandler();
    }
    @Bean
    public SimpleDriverDataSource dataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriverClass(org.mariadb.jdbc.Driver.class);
        dataSource.setUsername(_databaseConfig.getUsername());
        dataSource.setPassword(_databaseConfig.getPassword());
        dataSource.setUrl(_databaseConfig.getUrl());
        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setTypeHandlers(new TypeHandler[] {
            new DateTimeTypeHandler(),
        });
        sessionFactory.setTypeAliases(new Class[] {
            DateTime.class,
            Employee.class,
            DBObject.class,
            Snoop.class,
            SnoopDBObject.class
        });
        return sessionFactory;
    }
}
package com.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonBean {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();


        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);

//      # TEST 0 (TODO: see result when activated using JodaTime)
        mapper.registerModule(new JodaModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS );
//      mapper.setDateFormat(new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ (z)"));

//      # TEST 1 (Res: fail sometimes when too much depth)
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // true default

//      # TEST 2 (Res: too much depth)
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
                .setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY)
                .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
                .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

        return mapper;
    }

}
这很好,我能够序列化DateTime对象,但当我执行以下EmployeeServiceTest时,这不起作用:

package com.common.service.user;


import com.common.business.user.Employee;
import com.common.config.DataBean;
import com.commonTools.SessionIdentifierGenerator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

import static org.junit.Assert.*;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class, classes = {DataBean.class, EmployeeService.class})
public class EmployeeServiceTest implements EmployeeServiceDAO {

    private static final String SAMPLE_NAME = "JUnitTestUser_";

    @Autowired
    private EmployeeService _employeeService;


    private String getRandomName(){
        return SAMPLE_NAME + new SessionIdentifierGenerator().nextSessionId();
    }

    @Test
    public void test_getAll(){
        List<Employee> employeeList = this.getAll();
        Employee testEmployee = new Employee();
        testEmployee.setFirstName(getRandomName());
        testEmployee.setLastName(getRandomName());
        this.save(testEmployee);
        assertNotNull("should have an id", testEmployee.getId());
        List<Employee> employeeListIncremented = this.getAll();
        assertEquals("Should have +1 in list", employeeList.size() + 1 , employeeListIncremented.size());
        this.removeById(testEmployee.getId());
        assertTrue("should be deleted", this.getById(testEmployee.getId()) == null);
    }

    @Test
    public void test_getById(){
        Employee testEmployee = new Employee();
        testEmployee.setFirstName(getRandomName());
        testEmployee.setLastName(getRandomName());
        this.save(testEmployee);
        assertNotNull("should have an id", testEmployee.getId());
        Employee employeeById = this.getById(testEmployee.getId());
        assertEquals("should be equal id", employeeById.getId(), testEmployee.getId());
        this.removeById(testEmployee.getId());
        assertTrue("should be deleted", this.getById(testEmployee.getId()) == null);
    }

    @Test
    public void test_getFromFirstName(){
        Employee testEmployee = new Employee();
        testEmployee.setFirstName(getRandomName());
        testEmployee.setLastName(getRandomName());
        this.save(testEmployee);
        assertNotNull("should have an id", testEmployee.getId());
        Employee employeeFromFirstName = this.getFromFirstName(testEmployee.getFirstName());
        assertEquals("should be equal id", employeeFromFirstName.getId(), testEmployee.getId());
        this.removeById(testEmployee.getId());
        assertTrue("should be deleted", this.getById(testEmployee.getId()) == null);
    }

    @Test
    public void test_save() {
        Employee testEmployee = new Employee();
        testEmployee.setFirstName(getRandomName());
        testEmployee.setLastName(getRandomName());
        this.save(testEmployee);
        assertNotNull("should have an id", testEmployee.getId());
//      assertTrue("should have a creation datetime", null != testEmployee.getCreation().getDateTime() );
        String firstNameTmp = getRandomName();
        testEmployee.setFirstName(firstNameTmp);
        this.save(testEmployee);
        Employee editedEmployee = this.getById(testEmployee.getId());
        assertEquals("should have first name \""+firstNameTmp+"\"", firstNameTmp, editedEmployee.getFirstName());
        this.removeById(testEmployee.getId());
        assertTrue("should be deleted", this.getById(testEmployee.getId()) == null);
    }

    @Test
    public void test_removeById() {
        test_save();
    }

    public List<Employee> getAll() {
        return _employeeService.getAll();
    }

    public Employee getById(Integer id) {
        return _employeeService.getById(id);
    }

    public Employee getFromFirstName(String firstName) {
        return _employeeService.getFromFirstName(firstName);
    }

    public Employee save(Employee employee) {
        _employeeService.save(employee);
        return employee;
    }

    public void removeById(Integer id) {
        _employeeService.removeById(id);
    }
}
package com.common.service.user;
导入com.common.business.user.Employee;
导入com.common.config.DataBean;
导入com.commonTools.SessionIdentifierGenerator;
导入org.junit.Test;
导入org.junit.runner.RunWith;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
导入org.springframework.test.context.ContextConfiguration;
导入org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
导入java.util.List;
导入静态org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(initializers=ConfigFileApplicationContextInitializer.class,classes={DataBean.class,EmployeeService.class})
公共类EmployeeServiceTest实现EmployeeServiceDAO{
私有静态最终字符串示例;
@自动连线
私人雇员服务(EmployeeService);;
私有字符串getRandomName(){
返回示例名称+新SessionIdentifierGenerator().nextSessionId();
}
@试验
公共无效测试_getAll(){
List employeeList=this.getAll();
员工测试员工=新员工();
setFirstName(getRandomName());
setLastName(getRandomName());
这个.save(testEmployee);
assertNotNull(“应该有一个id”,testEmployee.getId());
List employeeListIncremented=this.getAll();
assertEquals(“列表中应有+1”,employeeList.size()+1,employeeListIncremented.size());
this.removeById(testEmployee.getId());
assertTrue(“应删除”,this.getById(testEmployee.getId())==null);
}
@试验
公共无效测试_getById(){
员工测试员工=新员工();
setFirstName(getRandomName());
setLastName(getRandomName());
这个.save(testEmployee);
assertNotNull(“应该有一个id”,testEmployee.getId());
Employee-employeeById=this.getById(testEmployee.getId());
assertEquals(“应该是相等的id”,employeeById.getId(),testEmployee.getId());
this.removeById(testEmployee.getId());
assertTrue(“应删除”,this.getById(testEmployee.getId())==null);
}
@试验
公共无效测试\u getFromFirstName(){
员工测试员工=新员工();
setFirstName(getRandomName());
setLastName(getRandomName());
这个.save(testEmployee);
assertNotNull(“应该有一个id”,testEmployee.getId());
Employee employeeFromFirstName=this.getFromFirstName(testEmployee.getFirstName());
assertEquals(“应该是相等的id”,employeeFromFirstName.getId(),testEmployee.getId());
this.removeById(testEmployee.getId());
assertTrue(“应删除”,this.getById(testEmployee.getId())==null);
}
@试验
公共无效测试_save(){
员工测试员工=新员工();
setFirstName(getRandomName());
setLastName(getRandomName());
这个.save(testEmployee);
assertNotNull(“应该有一个id”,testEmployee.getId());
//assertTrue(“应该有一个创建日期时间”,null!=testEmployee.getCreation().getDateTime());
字符串firstNameTmp=getRandomName();
testEmployee.setFirstName(firstNameTmp);
这个.save(testEmployee);
Employee editedEmployee=this.getById(testEmployee.getId());
assertEquals(“应该有名字\”“+firstNameTmp+”\”,firstNameTmp,editedEmployee.getFirstName());
this.removeById(testEmployee.getId());
assertTrue(“应删除”,this.getById(testEmployee.getId())==null);
}
@试验
公共无效测试\u removeById(){
test_save();
}
公共列表getAll(){
return _employeeService.getAll();
}
公共雇员getById(整数id){
return\u employeeService.getById(id);
}
公共员工getFromFirstName(字符串firstName){
return _employeeService.getFromFirstName(firstName);
}
公共雇员储蓄(雇员){
_employeeService.save(雇员);
返回员工;
}
public void removeById(整数id){
_employeeService.removeById(id);
}
}
这些问题浮现在我的脑海中:

  • 像DatabaseConfig那样序列化
    @Configuration
    类不是很方便,这是因为Spring在序列化链中还包括它自己的属性
  • UnitTest失败,原因是
    //assertTrue(“应该有一个创建日期时间”,null!=testEmployee.getCreation().getDateTime()),在测试中,getCreation为null,而它不应该为null,在测试期间我应该如何初始化Jackson到DateTime的Jodatime映射
  • 我还注意到测试失败时不会回滚数据库。我曾经使用javascript进行单元测试,我也曾经使用before()、after()方法进行测试的安装后和安装前,是否有一种简便的方法来实现这一点
  • 除了我在这里所做的一切之外,这是设计RESTful api的最合适的方法吗