我有一个问题。
我正在使用junit和dbunit测试我的dao。
如果我一个接一个地运行测试,一切都很好,但如果我运行所有测试,我有两个失败。我不明白为什么会这样。
public class VacancyDaoImplTest {
private VacancyDao vacancyDao;
@BeforeClass
public static void createSchema() throws Exception {
String db = "src\\test\\resources\\schema.sql";
RunScript.execute("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1",
"sa", "", db, UTF8, false);
}
@Before
public void setUp() {
ConnectionFactory connectionFactory = new ConnectionFactory();
vacancyDao = new VacancyDaoImpl(connectionFactory);
}
@Test
public void whenFindById_ThenReturnRightResult() {
Date date = new GregorianCalendar(2018, Calendar.APRIL, 1).getTime();
Vacancy microsoftVacancy = new Vacancy(1, "www.somewhere.org", "C# developer",
"from 3000 usd", "Microsoft", "Los Angele's, California, USA", date);
vacancyDao.insert(microsoftVacancy);
Vacancy result = vacancyDao.findById(1);
assertThat(microsoftVacancy, is(result));
}
@Test
public void whenInsertNewVacancy_ThenItInserted() {
Date jobDate = new GregorianCalendar(2018, Calendar.APRIL, 2).getTime();
Vacancy oracleVacancy = new Vacancy(1, "www.somewhere.org", "Java developer",
"from 3000 usd", "Oracle", "Redwood City, California, USA", jobDate);
vacancyDao.insert(oracleVacancy);
assertNotNull(vacancyDao.getAll());
}
@Test
public void whenGetAll_ThenGetAllVacancies() {
List<Vacancy> vacancyList = new ArrayList<>();
Date date = new GregorianCalendar(2018, Calendar.APRIL, 1).getTime();
Vacancy microsoftVacancy = new Vacancy(1,"www.somewhere.org", "C# developer",
"from 3000 usd", "Microsoft", "Los Angele's, California, USA", date);
vacancyList.add(microsoftVacancy);
vacancyDao.insert(microsoftVacancy);
List<Vacancy> result = vacancyDao.getAll();
assertArrayEquals(vacancyList.toArray(), result.toArray());
}
@Test
public void whenDeleteById_ThenItDeleted() {
Date date = new GregorianCalendar(2018, Calendar.APRIL, 1).getTime();
Vacancy microsoftVacancy = new Vacancy( 1,"www.somewhere.org", "C# developer",
"from 3000 usd", "Microsoft", "Los Angele's, California, USA", date);
vacancyDao.insert(microsoftVacancy);
vacancyDao.deleteById(1);
assertTrue(vacancyDao.getAll().isEmpty());
}
@Test
public void whenDeleteAll_ThenItEmpty() {
Date date = new GregorianCalendar(2018, Calendar.APRIL, 1).getTime();
Vacancy microsoftVacancy = new Vacancy( 1,"www.somewhere.org", "C# developer",
"from 3000 usd", "Microsoft", "Los Angele's, California, USA", date);
Vacancy oracleVacancy = new Vacancy(2,"www.somewhere.org", "Java developer",
"from 3000 usd", "Oracle", "Redwood City, California, USA", date);
vacancyDao.insert(microsoftVacancy);
vacancyDao.insert(oracleVacancy);
vacancyDao.deleteAll();
assertTrue(vacancyDao.getAll().isEmpty());
}
}
forFindById_ThenReturnRightResult()的stacktrace:
java.lang.AssertionError:
Expected: is null
but: was <Job{id=1, url='www.somewhere.org', title='C# developer',
salary='from 3000 usd', companyName='Microsoft', location='Los Angele's,
California, USA', date=Sun Apr 01 00:00:00 YEKT 2018}>
fortraleById_ThenItDeleted()的堆栈跟踪:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertTrue(Assert.java:52)
at
ru.skilanov.database.VacancyDaoImplTest.whenDeleteById_ThenItDeleted(VacancyDaoImplTest.java:106)
更新
好的,我检查了它并以不同的顺序运行,如果我删除所有检查删除方法的测试,它的工作原理。 那么我如何才能正确运行测试顺序?
我的道:
public class VacancyDaoImpl implements VacancyDao {
private static final String FIND_BY_COMPANY_NAME = "SELECT * FROM job WHERE company_name=?";
private static final String FIND_BY_ID = "SELECT * FROM job WHERE id=?";
private static final String DELETE_ALL = "DELETE FROM job";
private static final String DELETE_BY_ID = "DELETE FROM job WHERE id=?";
private static final String GET_ALL = "SELECT * FROM job";
private static final String INSERT = "INSERT INTO job (url, title, salary, company_name, location, create_date)" +
" VALUES (?,?,?,?,?,?)";
private ConnectionFactory connectionFactory;
public VacancyDaoImpl(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
@Override
public void insert(Vacancy vacancy) {
try (Connection connection = connectionFactory.getConnection();
PreparedStatement ps = connection.prepareStatement(INSERT)){
connection.setAutoCommit(false);
ps.setString(1, vacancy.getUrl());
ps.setString(2, vacancy.getTitle());
ps.setString(3, vacancy.getSalary());
ps.setString(4, vacancy.getCompanyName());
ps.setString(5, vacancy.getLocation());
ps.setDate(6, new Date(vacancy.getDate().getTime()));
ps.executeUpdate();
connection.commit();
} catch (SQLException sqle) {
throw new DaoException("Method insert has thrown an exception", sqle);
}
}
@Override
public List<Vacancy> getAll() {
List<Vacancy> jobsList = new ArrayList<>();
try (Connection connection = connectionFactory.getConnection();
Statement st = connection.createStatement()){
connection.setAutoCommit(false);
ResultSet rs = st.executeQuery(GET_ALL);
while (rs.next()) {
jobsList.add(new Vacancy(rs.getInt(Vacancy.ID),
rs.getString(Vacancy.COLUMN_URL),
rs.getString(Vacancy.COLUMN_TITLE),
rs.getString(Vacancy.COLUMN_SALARY),
rs.getString(Vacancy.COLUMN_COMPANY_NAME),
rs.getString(Vacancy.COLUMN_LOCATION),
rs.getTimestamp(Vacancy.COLUMN_CREATE_DATE)));
}
connection.commit();
} catch (SQLException sqle) {
throw new DaoException("Method getAll has thrown an exception", sqle);
}
return jobsList;
}
@Override
public List<Vacancy> findByCompanyName(String name) {
List<Vacancy> jobsList = new ArrayList<>();
try (Connection connection = connectionFactory.getConnection();
PreparedStatement ps = connection.prepareStatement(FIND_BY_COMPANY_NAME)){
connection.setAutoCommit(false);
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
jobsList.add(new Vacancy(rs.getInt(Vacancy.ID),
rs.getString(Vacancy.COLUMN_URL),
rs.getString(Vacancy.COLUMN_TITLE),
rs.getString(Vacancy.COLUMN_SALARY),
rs.getString(Vacancy.COLUMN_COMPANY_NAME),
rs.getString(Vacancy.COLUMN_LOCATION),
rs.getTimestamp(Vacancy.COLUMN_CREATE_DATE)));
}
connection.commit();
} catch (SQLException sqle) {
throw new DaoException("Method findByCompanyName has thrown an exception", sqle);
}
return jobsList;
}
@Override
public Vacancy findById(int id) {
try (Connection connection = connectionFactory.getConnection();
PreparedStatement ps = connection.prepareStatement(FIND_BY_ID)){
connection.setAutoCommit(false);
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
return new Vacancy(rs.getInt(Vacancy.ID),
rs.getString(Vacancy.COLUMN_URL),
rs.getString(Vacancy.COLUMN_TITLE),
rs.getString(Vacancy.COLUMN_SALARY),
rs.getString(Vacancy.COLUMN_COMPANY_NAME),
rs.getString(Vacancy.COLUMN_LOCATION),
rs.getTimestamp(Vacancy.COLUMN_CREATE_DATE));
}
connection.commit();
} catch (SQLException sqle) {
throw new DaoException("Method findById has thrown an exception", sqle);
}
return null;
}
@Override
public void deleteById(int id) {
try (Connection connection = connectionFactory.getConnection();
PreparedStatement ps = connection.prepareStatement(DELETE_BY_ID)){
connection.setAutoCommit(false);
ps.setInt(1, id);
ps.executeUpdate();
connection.commit();
} catch (SQLException sqle) {
throw new DaoException("Method deleteById has thrown an exception", sqle);
}
}
@Override
public void deleteAll() {
try (Connection connection = connectionFactory.getConnection();
PreparedStatement ps = connection.prepareStatement(DELETE_ALL)){
connection.setAutoCommit(false);
ps.executeUpdate();
connection.commit();
} catch (SQLException sqle) {
throw new DaoException("Method deleteAll has thrown an exception", sqle);
}
}
}
答案 0 :(得分:1)
问题不在于测试本身的顺序,而是它们中的一些是创建记录而不是删除它们然后你正在检查是否有记录,这显然是失败的。最好的方法是在每次测试执行之前清空所有记录:
@Before
public void setUp() {
ConnectionFactory connectionFactory = new ConnectionFactory();
vacancyDao = new VacancyDaoImpl(connectionFactory);
vacancyDao.deleteAll();
}
或者,如果测试负责创建和删除单个记录,那么您应该断言已删除单个记录,而不是像这种情况下的所有记录:
@Test
public void whenDeleteById_ThenItDeleted() {
Date date = new GregorianCalendar(2018, Calendar.APRIL, 1).getTime();
Vacancy microsoftVacancy = new Vacancy( 1,"www.somewhere.org", "C# developer",
"from 3000 usd", "Microsoft", "Los Angele's, California, USA", date);
vacancyDao.insert(microsoftVacancy);
vacancyDao.deleteById(1);
//assertTrue(vacancyDao.getAll().isEmpty());
assertNull(vacancyDao.get(id)); // Assuming you have a DAO method that returns null if a record is not present in the DB
}
答案 1 :(得分:1)
感谢您的回答。
<强>解强>
之所以发生这种情况,是因为当我试图通过id找工作时,这不是预期的价值。
所以我在每次测试后重置计数器:
@After
public void tearDown() throws Exception {
vacancyDao.deleteAll();
try (Connection connection = new ConnectionFactory().getConnection()) {
Statement statement = connection.createStatement();
statement.executeUpdate("ALTER TABLE job ALTER COLUMN id RESTART WITH 1");
}
}
答案 2 :(得分:0)
我不会处理测试顺序,而是使用不同的DB名称为每个测试方法设置模式。