2017-07-17 5 views
1

Ich schreibe einen Integrationstest zwischen meiner JPA-Schicht und der Datenbank, um zu überprüfen, ob die von mir geschriebene SQL korrekt ist. Die eigentliche Datenbank ist Oracle, leider aus Gründen meiner Kontrolle muss meine Testdatenbank Derby sein, so natürlich gibt es einige Unterschiede. Zum Beispiel meine PPV-Klasse hat die folgende SQL-String-KonstanteJMockit Deencapsulation setField nicht persistent

private static final String QUERY = "Select * from Users where regexp_like(user_code, '^SS(B)?N')"; 

Weil Derby nicht regexp_like unterstützt Ich verwende JMockits Deencapsulation.setField die SQL-on the fly zu ändern. z.B.

@Test 
public void testMyDaoFind() { 
    new Expectations() { 
     { 
      Deencapsulation.setField(MyClass.class, "QUERY", "Select * from Users"); 
     } 
    }; 

    dao.findUsers(); 
} 

ignorieren nun die Tatsache, dass dies nicht ein guter Test, da es nicht die tatsächliche Abfrage testet, die auf der realen Datenbank ausgeführt wird (dies rein ist mein curiousity gerecht zu werden, was vor sich geht), Ich bekomme einen SQL-Ausnahmefehler von Eclipselink/Derby beschweren sich über Regexp_like wird nicht als eine Funktion oder eine Prozedur erkannt.

Wenn ich einen Haltepunkt auf der Linie in der DAO platzieren, die die Ergebnisliste zu bekommen versucht, kann ich von einer neuen Uhr sehen, dass

  1. JMockit die Abfrage richtig

  2. ersetzt hat

    getResultList() gibt die Daten ich erwarte

sehen Wenn jedoch lasse ich den Test den ganzen Weg durchlaufen dann erhalte ich die afformentioned Ausnahme ?!

Antwort

2

Strings in Java werden nicht so behandelt, wie Sie denken. Der Java-Quellcompiler ersetzt Lesevorgänge aus Feldern, die String-Literale enthalten, durch die feste "Adresse", in der die Zeichenfolge gespeichert ist (im Konstantenpool der Klasse). Das Feld wird zur Laufzeit nicht mehr gelesen. Selbst wenn JMockit die im Feld gespeicherte String-Referenz ersetzt, macht dies keinen Unterschied, da diese Referenz vom Client-Code, der das Feld verwendet, nicht erkannt wird.

(BTW, warum die Probe zu stellen sind, um den Anruf zu Deencapsulatin.setField innerhalb eines Erwartungs Block? Solche Blöcke nur für die Aufnahme Erwartungen gemeint ...)

Unterm Strich gibt es keine Möglichkeit zu erreichen, was du bist versuchen. Verwenden Sie stattdessen entweder eine Oracle-Datenbank für Integrationstests oder machen Sie den gesamten SQL-Code portierbar, indem Sie RDBMS-spezifische Funktionen wie regexp_like vermeiden.

+0

Sehr informativ danke! – PDStat