zoukankan      html  css  js  c++  java
  • Spring DBUnit 插入数据的时候如何处理自增ID

    Spring DBUnit 插入数据的时候如何处理自增ID

    今天在补单元测试的时候遇到一个问题,在给插入数据的方法写单元测试的时候,第一遍运行的时候是没问题,第二遍运行就报错了,如下:

    junit.framework.ComparisonFailure: value (table=FACULTY_ROOM, row=2, col=id) 
    Expected :3
    Actual   :4
     <Click to see difference>
       at org.dbunit.assertion.JUnitFailureFactory.createFailure(JUnitFailureFactory.java:39)
    	at org.dbunit.assertion.DefaultFailureHandler.createFailure(DefaultFailureHandler.java:97)
    	at org.dbunit.assertion.DefaultFailureHandler.handle(DefaultFailureHandler.java:223)
    	at org.dbunit.assertion.DbUnitAssert.compareData(DbUnitAssert.java:524)
    	at org.dbunit.assertion.DbUnitAssert.assertEquals(DbUnitAssert.java:409)
    	at org.dbunit.assertion.DbUnitAssert.assertEquals(DbUnitAssert.java:312)
    	at org.dbunit.assertion.DbUnitAssert.assertEquals(DbUnitAssert.java:274)
    	at org.dbunit.assertion.DbUnitAssert.assertEqualsIgnoreCols(DbUnitAssert.java:122)
    	at org.dbunit.Assertion.assertEqualsIgnoreCols(Assertion.java:74)
    	at com.github.springtestdbunit.assertion.NonStrictDatabaseAssertion.assertEquals(NonStrictDatabaseAssertion.java:56)
    	at com.github.springtestdbunit.assertion.NonStrictDatabaseAssertion.assertEquals(NonStrictDatabaseAssertion.java:48)
    	at com.github.springtestdbunit.DbUnitRunner.verifyExpected(DbUnitRunner.java:154)
    	at com.github.springtestdbunit.DbUnitRunner.verifyExpected(DbUnitRunner.java:120)
    	at com.github.springtestdbunit.DbUnitRunner.afterTestMethod(DbUnitRunner.java:86)
    	at com.github.springtestdbunit.DbUnitTestExecutionListener.afterTestMethod(DbUnitTestExecutionListener.java:190)
    	at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:319)
    	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:94)
    	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)`
    

    第一遍运行成功是因为第一次插入数据到测试数据库时,从原始数据ID=2增长到ID=3,和预期一致,后面执行完毕,数据虽然回滚删除了,但是自增ID的游标没变,下次插入数据ID就是从4开始的,所以与预期的ID=3不一致,我的代码和数据文件如下:

    @Test
    @ExpectedDatabase(value = "facultyService.createFaculty.expectedData.xml", assertionMode = DatabaseAssertionMode.NON_STRICT)
    public void testCreateFaculty() {
        Faculty faculty = new Faculty();
        faculty.setCode("rjgc");
        faculty.setName("软件工程");
        faculty.setAbbreviation("rjgc");
        facultyService.createFaculty(faculty);
    }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <dataset>
    <FACULTY id="1" code="jsj" name="计算机系" abbreviation="jsj"/>
    <FACULTY id="2" code="cstmgc" name="测试更新土木工程系" abbreviation="cstmgc"/>
    </dataset>
    

    解决方法:在插入操作之前把ID自增的游标定位到当前初始数据的最大ID处,下一次插入数据的ID就是最大ID+1,代码如下:

    package test.edu.util;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.core.env.Environment;
    
    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public final class DbTestUtil {
            //test.reset.sql.maxId = SELECT max(Id) FROM %s;
        private static final String MAX_ID = "test.reset.sql.maxId";
        //test.reset.sql.template = ALTER TABLE %s AUTO_INCREMENT = maxId;
        private static final String RESET = "test.reset.sql.template";
    
        private DbTestUtil() {
        }
    
        public static void resetAutoIncrementColumns(ApplicationContext applicationContext,
                                                     String... tableNames) throws SQLException {
            DataSource dataSource = applicationContext.getBean(DataSource.class);
            String resetSqlTemplate = getResetSqlTemplate(applicationContext, RESET);
            String getMaxIdTemplate = getResetSqlTemplate(applicationContext, MAX_ID);
            try (Connection dbConnection = dataSource.getConnection()) {
                //Create SQL statements that reset the auto increment columns and invoke
                //the created SQL statements.
                for (String resetSqlArgument : tableNames) {
                    try (Statement statement = dbConnection.createStatement()) {
                        String maxId = String.format(getMaxIdTemplate, resetSqlArgument);
                        ResultSet resultSet = statement.executeQuery(maxId);
                        if (resultSet.next()) {
                            String id = resultSet.getString(1);
                            String resetSql = String.format(resetSqlTemplate, resetSqlArgument);
                            resetSql = resetSql.replace("maxId", id);
                            statement.execute(resetSql);
                        }
                    }
                }
            }
        }
    
        private static String getResetSqlTemplate(ApplicationContext applicationContext, String option) {
            //Read the SQL template from the properties file
            Environment environment = applicationContext.getBean(Environment.class);
            return environment.getRequiredProperty(option);
        }
    }
    
    
    @DatabaseSetup("facultyService.data.xml")
    public class FacultyServiceTest extends BaseServiceTest {
    	@Autowired
    	private FacultyService facultyService;
    	
    	@Autowired
    	private ApplicationContext applicationContext;
    	
    	@Before
    	public void setUp() throws SQLException {
    	    DbTestUtil.resetAutoIncrementColumns(applicationContext, "faculty", "faculty_room");
    	}
    	
    	@Test
    	@ExpectedDatabase(value = "facultyService.createFaculty.expectedData.xml", assertionMode = DatabaseAssertionMode.NON_STRICT)
    	public void testCreateFaculty() {
    	    Faculty faculty = new Faculty();
    	    faculty.setCode("rjgc");
    	    faculty.setName("软件工程");
    	    faculty.setAbbreviation("rjgc");
    	    facultyService.createFaculty(faculty);
    	}
    }
    

    如果还有什么问题,可以在下面留言。

  • 相关阅读:
    知多少进程?
    提高.NET应用性能
    战术设计DDD
    win7下exe文件设置为开机启动
    CQRS项目
    DDD总览
    ML.Net Model Builder
    MySQL主主复制搭建教程收集(待实践)
    MySQL主从复制搭建教程收集(待实践)
    MySQL集群方案收集
  • 原文地址:https://www.cnblogs.com/ekoeko/p/9508250.html
Copyright © 2011-2022 走看看