3 Stimmen

Spring Transaction Management Test

Ich möchte meine Dao-Klasse mit den SpringContextTests testen.
In meiner Methodenklasse habe ich die AbstractTransactionalJUnit4SpringContextTests damit meine Testklasse mit JUnit4 integriert werden kann. Ich habe auch die Konfigurationen eingerichtet und die Initialisierung und Datenbankbereinigung in der @Before und tearDown in der @After . Meine Testklasse funktioniert perfekt.

Mein Problem war, wenn ich meine Testklasse ausführe und die Datenbank mit Daten gefüllt wird, wurden die ursprünglichen Daten nicht zurückgerollt und meine Datenbank wird geleert. In der @Before Methode lösche ich die Datenbank und fülle die Daten auf, wobei ich denke, dass ich in der Lage sein werde, es wiederherzustellen, aber das ist nicht der Fall.

Kann jemand ein Beispiel nennen, das funktioniert und die Informationen in der Datenbank zurücksetzt?

ADDONS:
Jede Datenbankmanipulation in meinen Testmethoden wird rückgängig gemacht. Aber die Ausführung von super.deleteFromTables("person") en el @Before Methode nicht alle vorherigen Daten aus der Datenbank wiederhergestellt hat.

Spring rollt alle CRUD-Operationen zurück, aber die Datenbankbereinigung vor der Transaktion wird nicht zurückgesetzt.

2voto

Roy Marco Aruta Punkte 687

Vielen Dank an alle, die meine Frage beantwortet haben. Ich habe viel aus den Antworten gelernt, aber mein Problem wurde dadurch nicht gelöst.
Ich wusste, dass meine Testdaten ein Transaktionsmanagement durchführen und dass es seine Aufgabe richtig erfüllt.
Der Fehler liegt bei mir.

Ich habe die Lektion über Datenbankbefehle vergessen, dass eine DDL-Anweisung, die nach einer DML-Anweisung ausgeführt wird, automatisch die Transaktion festschreibt. Ich führte eine DDL-Anweisung nach einer DML-Anweisung aus, indem ich alle Datensätze löschte und dann ALTER el AUTO_INCREMENT der Tabelle, in der es einen Auto-Commit auslöst und alle Datensätze der Tabelle dauerhaft löscht.

DIE BEHEBUNG DIESES SZENARIOS HAT MEIN PROBLEM GELÖST.

1voto

Robert Munteanu Punkte 64955

Mögliche Ursachen:

  • Sie verwenden eine Datenbank/Datenbank-Engine, die nicht über geeignete Transaktionen verfügt;
  • Sie verwenden mehrere Transaktionsmanager und/oder Datenquellen, und die richtige wird nicht abgeholt;
  • Sie führen Ihre eigenen, separaten Transaktionen in der Testklasse durch.

Hier ist ein Beispiel (aus dem Kopf, nicht kompiliert)

public class DBTest extends AbstractTransactionalJUnit4SpringContextTests {

    @Autowired
    private SomeDAO _aBeanDefinedInMyContextFile;

    @Test
    public void insert_works() {
        assert _aBeanDefinedInMyContextFile.findAll() == 0;
        _aBeanDefinedInMyContextFile.save(new Bean());
        assert _aBeanDefinedInMyContextFile.findAll() == 1;
    }

}

Wichtige Punkte:

  • el SomeDAO ist eine Schnittstelle, die einer in meinem Kontext deklarierten Bean entspricht;
  • die Bean hat keine transaktionalen Einstellungen (advice/programmatic), sie ist darauf angewiesen, dass der Aufrufer transaktional ist - entweder der Dienst in der Produktion oder der Test in unserer Situation;
  • der Test enthält keinen Code für die Transaktionsverwaltung, da dies alles im Framework geschieht.

1voto

Pablojim Punkte 8312

Ich bin mir nicht sicher, was mit Ihrer Klasse los ist. Hier ist ein Auszug aus einer Klasse, die das tut, was Sie mit dbunit und spring 2.5 wollen:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
  "testContext.xml"})
@TransactionConfiguration
@Transactional
public class SampleDAOTest {

    @Autowired
    private DataSource dataSource;
    @Autowired
    private SampleDAO sampleDAO;

    @Before 
    public void onSetUpInTransaction() throws Exception {
        //Populate Test data
        IDatabaseConnection dbUnitCon = new DatabaseConnection(DataSourceUtils.getConnection(dataSource), "DATASOURCE");
            //read in from a dbunit excel file of test data
        IDataSet dataSet = new XlsDataSet(new File("src/test/resources/TestData.xls"));
        DatabaseOperation.INSERT.execute(dbUnitCon, dataSet);
    }

    @Test
    public void testGetIntermediaryOrganisation() {

        // Test getting a user
        User object = sampleDAO.getUser(99L);
        assertTrue(object.getValue);

    }
}

Einer der Vorteile dieser Methode ist, dass Sie keine Klassen erweitern müssen. Sie können also weiterhin Ihre eigene Hierarchie für Tests haben.

Wenn Sie wirklich an Ihrer aktuellen Methode festhalten wollen, anstatt die @before-Annotation zu verwenden, müssen Sie die unten stehende Methode überschreiben und Ihren Setup-Code dort einfügen.

@Override
public void onSetUpInTransaction() throws Exception {...}

Ich hoffe, das hilft

0voto

Confusion Punkte 15269

Abgesehen von Ihrer Frage schlage ich vor, dass Sie eine separate Datenbankinstanz verwenden, gegen die Sie Ihre Tests durchführen. Auf diese Weise können Sie sie sicher löschen und Ihre Tests können sie nach Bedarf initialisieren.

Soweit ich weiß, unterstützen die Spring-Klassen für Datenbanktests nur das Rollback, was in den Tests passiert, nicht das, was beim Auf- und Abbau der Tests passiert.

0voto

Cuga Punkte 17251

Zustimmen mit Verwirrung - Sie sollten Ihre Tests gegen ihre eigenen Datenbankschema ausgeführt werden.

Damit können Sie Ihre Hibernate-Eigenschaften auf "create-drop" einstellen:

Mit create-drop wird das Datenbankschema gelöscht, wenn die SessionFactory explizit geschlossen wird.

Voir : Optionale Eigenschaften der Hibernate-Konfiguration

Beispiel Ausschnitt:

<bean id="sessionBean" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
         ...etc

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X