2015-09-28 11 views
5

Dies ist sicherlich ein häufiges Problem. Ich habe eine Eigenschaftendatei wie my-settings.properties, die von einer Anwendungsklasse gelesen wird. Wenn ich eine Testklasse schreibe, muss sie verschiedene Szenarien von Dingen testen, die in my-settings.properties vorhanden sein könnten, um eine maximale Codeabdeckung sicherzustellen (z. B. leere Eigenschaftendatei, grundlegende Eigenschaftendatei usw.). Aber ich kann nur einen my-settings.properties in meinem src/test/resources haben.Wie kann ich das Vorhandensein einer Eigenschaftendatei im Klassenpfad verspotten?

Was wirklich groß sein würde, wenn es nur einige Anmerkung

@MockFileOnClassPath(use = "my-settings-basic.properties", insteadOf = "my-settings.properties")

war

Dann konnte ich einfach haben mehrere my-settings-XXX.properties Dateien in meinem /src/test/resources und kommentierte nur das richtige für jedes Testverfahren. Aber ich kann so etwas nicht finden. Ich benutze JUnit 4.12.

Ich denke an ein paar rohen Lösungen:

  1. Vor jeder Prüfung die Datei auf dem Dateisystem finden, kopieren Sie es Dateisystem mit I/O, es dann nach dem Test wieder gelöscht werden. Aber das ist ungeschickt und beinhaltet eine Menge Redundanz. Ganz zu schweigen davon, dass ich nicht einmal sicher bin, ob das Klassenpfadverzeichnis beschreibbar sein wird.
  2. Verwenden Sie ein spöttisches Framework, um getResource nachzuahmen. Keine Ahnung, wie ich auch das tun würde, zumal es eine Million verschiedene Möglichkeiten, um die Datei zu erhalten (, MyClass.class.getResourceAsStream(...), ClassLoader.getSystemClassLoader().getResourceAsStream(...) usw.)

Ich denke nur, dies ist ein häufiges Problem und vielleicht sein muss, gibt es bereits eine Lösung in JUnit, Mockito, PowerMock, EasyMock oder so ähnlich?

BEARBEITEN: Jemand hat angegeben, dass diese Frage ein Duplikat von Specifying a custom log4j.properties file for all of JUnit tests run from Eclipse ist, aber es ist nicht. In dieser Frage geht es darum, eine andere Eigenschaftendatei zwischen den Haupt- und Testaufrufen zu haben. Für mich möchte ich eine andere Eigenschaftendatei zwischen einem Testaufruf und einem anderen Testaufruf haben.

+1

Das ist eine wirklich gute Frage. Holen Sie ein 'Properties'-Objekt häufig genug, um das auszugeben?Obwohl es eine Million Möglichkeiten gibt, Eigenschaften zu erhalten, greift Ihr Code auf die Eigenschaftendatei in einer einheitlichen Weise zu, wodurch einige Ihrer Testvektoren eliminiert würden, die Sie nachahmen müssten. Oder ist es eine Black Box, und Sie wissen es nicht? –

+1

Mein Code ruft derzeit die Eigenschaften auf eine einheitliche Weise ab, aber ich möchte nicht, dass mein Test in Zukunft fehlschlägt, nur weil jemand die Art geändert hat, in der eine Eigenschaftendatei abgerufen wurde. Nicht sicher, was du mit "stub that out" meinst. Meinen Sie den Konstruktor und die 'load' Methode der' Properties' Klasse zu spotten, um nichts zu tun, und dann die 'getProperty' Methode vortäuschen, um nur Eigenschaften von einer Map zurückzugeben, die ich in meiner Testklasse erstellt habe? Das ist eine gute Idee ... obwohl es nicht helfen würde zu verifizieren, dass ich den richtigen Dateinamen an 'getResourceAsStream' (etc.) übergebe. – Kidburla

+0

Ja, das ist es, was ich vorschlage, und du hast Recht, es ist nicht zukunftssicher. Ich denke, dass die Überprüfung des korrekten Dateinamens ein anderer Test sein sollte ... –

Antwort

1

Ich finde, dass es am besten ist, wenn man sich mit Dateien beschäftigt, das Konzept einer Resource einzuführen.

zB:

public interface Resource { 
    String getName(); 
    InputStream getStream(); 
} 

Dann Sie die Ressource in über Dependency Injection passieren kann:

public class MyService { 
    private final Properties properties; 

    public class MyService(Resource propFile) { 
     this.properties = new Properties(); 
     this.properties.load(propFile.getStream()); 
    } 

    ... 
} 

Dann in Ihrem Produktionscode Sie ClasspathResource oder vielleicht ein FileResource oder URLResource usw. verwenden können, aber in deinen Tests könntest du eine StringResource usw. haben

Anmerkung, wenn du Frühling verwendest, hast du bereits ein impl Entwicklung dieses Konzepts. Weitere Details here

+0

Die Konsumenten meiner Klasse sollten nicht wissen müssen, wo sich die Eigenschaftendatei befindet. Natürlich könnte ich einen Nullary-Konstruktor erstellen, der 'DEFAULT_RESOURCE' nur an den Konstruktor mit einem Argument übergibt, aber dann ruft mein Consumer eine andere Methode als meine Testklasse auf. – Kidburla

+0

Das ist, was ich tun würde, ist es üblich, Methoden hinzuzufügen, um das Testen einfacher zu machen ... Ich würde den einen Arg-Konstruktor eher geschützt als öffentlich machen, da es nur zum Testen ist –

+0

Oh, du meinst paketgeschützt? Dies könnte die beste Idee für die verfügbaren Lösungen sein. Ich bin immer noch ziemlich überrascht, dass es für dieses Problem keine Lösung von der Stange gibt! – Kidburla

2

Sie können Ihre Service Klasse ändern den Namen der resource Datei zu akzeptieren, dann verwenden Sie dann, dass name die resource zu laden.

public class MyService { 

public MyService(String resourceFileName){ 
    //and load it into Properties getResourceAsStream(resourceFileName); 
} 
} 
+0

Dies ist im Grunde, was @ LanceJava vorgeschlagen hat, nur mit einer Ressource statt einer Zeichenfolge ... – Kidburla

Verwandte Themen