为什么不是@Transactional和@Rollback回滚单元测试?

时间:2017-11-22 21:24:42

标签: hibernate spring-boot junit

我是一个写作单元测试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;
    }
}

这是我长期以来的第一个问题;对不起,如果我没有正确格式化

0 个答案:

没有答案