我是一个写作单元测试DAO,我试图确保每个测试回滚所做的任何更改。我已经通过user2418306咨询了答案Rollback transaction after @Test,并设置了相应的数据源和事务管理器bean。但是,@ Transaction和@Rollback注释仍无法正常工作 - getCommentBySubreddit_Success()所做的更改会影响getCommentBySubreddit_Fail()。
摇篮
buildscript {
ext {
springBootVersion = '1.5.8.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.subredditstats'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-rest')
compile group: 'com.fasterxml', name: 'jackson-module-json-org', version: '0.9.1'
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '1.4.0.RELEASE'
// Hibernate
compile('org.hibernate:hibernate-core:5.1.0.Final')
/*compile group: 'org.springframework', name: 'spring-orm', version: '3.1.1.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.1.7.Final'*/
// SQlite
compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.7.2'
compile group: 'org.hibernate.dialect', name: 'sqlite-dialect', version: '0.1.0'
testCompile group: 'com.h2database', name: 'h2', version: '1.0.60'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile group: 'com.h2database', name: 'h2', version: '1.3.148'
testCompile group: 'org.springframework.security', name: 'spring-security-test'
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.1.0'
testCompile group: 'com.fasterxml', name: 'jackson-module-json-org', version: '0.9.1'
}
单元测试
package com.subredditstats.api.statistics;
import com.subredditstats.api.content.ContentController;
import com.subredditstats.api.content.model.Comment;
import com.subredditstats.api.content.model.CommentEntry;
import com.subredditstats.api.helper.DatabaseBean;
import com.subredditstats.api.helper.DatabaseOperation;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=DatabaseBean.class)
@Transactional()
public class StatisticsDAOTest {
@Autowired
@Qualifier("testDatabase")
private SessionFactory sessionFactory;
private StatisticsDAO dao;
@Before
public void setUp(){
dao = new StatisticsDAOImpl(sessionFactory);
}
@After
public void tearDown(){
}
@Test
@Rollback(true)
public void getCommentBySubreddit_Success(){
// Arrange
CommentEntry comment1 = new CommentEntry();
comment1.setSubreddit("a");
DatabaseOperation.persist(sessionFactory,comment1);
// Act
List<Comment> comments = dao.getCommentsBySubreddit("a");
// Assert
comments.forEach(comment -> Assert.assertEquals(comment.getSubreddit(),"a"));
}
@Test
@Rollback(true)
public void getCommentBySubreddit_Fail(){
// Arrange
// Act
List<Comment> comments = dao.getCommentsBySubreddit("a");
// Assert
Assert.assertEquals(0,comments.size());
// This fails since a comment with id "a" already exists in the database, due to the effects of getCommentBySubreddit_Success()
}
}
DatabaseOperation
public class DatabaseOperation {
public static void persist(SessionFactory sessionFactory,Object object){
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(object);
session.getTransaction().commit();
session.close();
}
}
DatabaseBean
package com.subredditstats.api.helper;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
@Configuration
@PropertySource("application.properties")
public class DatabaseBean {
@Autowired
Environment env;
@Bean("testDatabase")
public SessionFactory createSessionFactory(){
SessionFactory sessionFactory = null;
// A SessionFactory is set up once for an application!
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure() // configures settings from hibernate.cfg.xml
.build();
try {
sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
}
catch (Exception e) {
// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
// so destroy it manually.
e.printStackTrace();
StandardServiceRegistryBuilder.destroy( registry );
}
return sessionFactory;
}
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(
env.getProperty("datasource.url"),
env.getProperty("datasource.user"),
env.getProperty("datasource.password")
);
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
hibernate.cfg.xml中
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.dialect">com.subredditstats.api.database.SQLiteDialect</property>
<property name="hibernate.connection.driver_class">org.sqlite.JDBC</property>
<property name="hibernate.connection.url">jdbc:sqlite::memory:</property>
<property name="hibernate.connection.username"></property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.hbm2ddl.auto">create</property>
<!-- add classes to map from here -->
<mapping class="com.subredditstats.api.content.model.CommentEntry" />
<mapping class="com.subredditstats.api.content.model.SubmissionEntry"/>
</session-factory>
</hibernate-configuration>
application.properties
datasource.url=jdbc:sqlite::memory:
datasource.user=
datasource.password=
CommentEntry
package com.subredditstats.api.content.model;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@Entity
@Table(name="comment")
public class CommentEntry {
@Id
@Column(name="commentId")
private String commentId;
private int upvotes;
private int downvotes;
private String text;
private boolean gilded;
private String author;
private String subreddit;
public CommentEntry(){
this("000000",0,0,
"text", false,
"author","subreddit");
}
public CommentEntry(String id, int upvotes,
int downvotes, String text,
boolean gilded,String author,
String subreddit){
this.commentId = id;
this.upvotes = upvotes;
this.downvotes = downvotes;
this.text = text;
this.gilded = gilded;
this.author = author;
this.subreddit = subreddit;
}
public Comment createComment(){
return new Comment(commentId,upvotes,
downvotes,text,gilded,author,subreddit);
}
public static List<Comment> mapToComment(List<CommentEntry> commentEntries){
List<Comment> comments = new ArrayList<>();
Iterator<CommentEntry> iterator = commentEntries.iterator();
while(iterator.hasNext()){
comments.add(iterator.next().createComment());
}
return comments;
}
public String getCommentId() {
return commentId;
}
public int getUpvotes() {
return upvotes;
}
public int getDownvotes() {
return downvotes;
}
public String getText() {
return text;
}
public boolean isGilded() {
return gilded;
}
public String getAuthor() {
return author;
}
public String getSubreddit() {
return subreddit;
}
public void setCommentId(String commentId) {
this.commentId = commentId;
}
public void setUpvotes(int upvotes) {
this.upvotes = upvotes;
}
public void setDownvotes(int downvotes) {
this.downvotes = downvotes;
}
public void setText(String text) {
this.text = text;
}
public void setGilded(boolean gilded) {
this.gilded = gilded;
}
public void setAuthor(String author) {
this.author = author;
}
public void setSubreddit(String subreddit) {
this.subreddit = subreddit;
}
}
这是我长期以来的第一个问题;对不起,如果我没有正确格式化