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);
	}
}

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

posted on 2018-08-20 21:28  ekoeko  阅读(355)  评论(0编辑  收藏  举报

导航