Einfacher Weg, um eine Testdatei in JUnit zu bekommen

78

Kann jemand einen einfachen Weg vorschlagen, um einen Verweis auf eine Datei als Objekt vom Typ String / InputStream / File / etc in einer Junit-Testklasse zu erhalten? Natürlich könnte ich die Datei (in diesem Fall XML) als riesigen String einfügen oder als Datei einlesen, aber gibt es eine für Junit spezifische Verknüpfung wie diese?

public class MyTestClass{

@Resource(path="something.xml")
File myTestFile;

@Test
public void toSomeTest(){
...
}

}
benstpierre
quelle

Antworten:

85

Sie können @RuleAnnotation versuchen . Hier ist das Beispiel aus den Dokumenten:

public static class UsesExternalResource {
    Server myServer = new Server();

    @Rule public ExternalResource resource = new ExternalResource() {
        @Override
        protected void before() throws Throwable {
            myServer.connect();
        };

        @Override
        protected void after() {
            myServer.disconnect();
        };
    };

    @Test public void testFoo() {
        new Client().run(myServer);
    }
}

Sie müssen nur eine FileResourceKlassenerweiterung erstellen ExternalResource.

Vollständiges Beispiel

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

public class TestSomething
{
    @Rule
    public ResourceFile res = new ResourceFile("/res.txt");

    @Test
    public void test() throws Exception
    {
        assertTrue(res.getContent().length() > 0);
        assertTrue(res.getFile().exists());
    }
}

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

import org.junit.rules.ExternalResource;

public class ResourceFile extends ExternalResource
{
    String res;
    File file = null;
    InputStream stream;

    public ResourceFile(String res)
    {
        this.res = res;
    }

    public File getFile() throws IOException
    {
        if (file == null)
        {
            createFile();
        }
        return file;
    }

    public InputStream getInputStream()
    {
        return stream;
    }

    public InputStream createInputStream()
    {
        return getClass().getResourceAsStream(res);
    }

    public String getContent() throws IOException
    {
        return getContent("utf-8");
    }

    public String getContent(String charSet) throws IOException
    {
        InputStreamReader reader = new InputStreamReader(createInputStream(),
            Charset.forName(charSet));
        char[] tmp = new char[4096];
        StringBuilder b = new StringBuilder();
        try
        {
            while (true)
            {
                int len = reader.read(tmp);
                if (len < 0)
                {
                    break;
                }
                b.append(tmp, 0, len);
            }
            reader.close();
        }
        finally
        {
            reader.close();
        }
        return b.toString();
    }

    @Override
    protected void before() throws Throwable
    {
        super.before();
        stream = getClass().getResourceAsStream(res);
    }

    @Override
    protected void after()
    {
        try
        {
            stream.close();
        }
        catch (IOException e)
        {
            // ignore
        }
        if (file != null)
        {
            file.delete();
        }
        super.after();
    }

    private void createFile() throws IOException
    {
        file = new File(".",res);
        InputStream stream = getClass().getResourceAsStream(res);
        try
        {
            file.createNewFile();
            FileOutputStream ostream = null;
            try
            {
                ostream = new FileOutputStream(file);
                byte[] buffer = new byte[4096];
                while (true)
                {
                    int len = stream.read(buffer);
                    if (len < 0)
                    {
                        break;
                    }
                    ostream.write(buffer, 0, len);
                }
            }
            finally
            {
                if (ostream != null)
                {
                    ostream.close();
                }
            }
        }
        finally
        {
            stream.close();
        }
    }

}

Ha.
quelle
9
Beeindruckend. Sieht so aus, als wäre es meine bisher beste Antwort. Ich bin wirklich schlecht darin, die Zukunft vorherzusagen.
Ha.
77

Wenn Sie tatsächlich ein FileObjekt benötigen , können Sie Folgendes tun:

URL url = this.getClass().getResource("/test.wsdl");
File testWsdl = new File(url.getFile());

Welches den Vorteil hat, plattformübergreifend zu arbeiten, wie in diesem Blog-Beitrag beschrieben .

Slashnick
quelle
14

Ich weiß, dass Sie gesagt haben, Sie wollten die Datei nicht von Hand einlesen, aber das ist ziemlich einfach

public class FooTest
{
    private BufferedReader in = null;

    @Before
    public void setup()
        throws IOException
    {
        in = new BufferedReader(
            new InputStreamReader(getClass().getResourceAsStream("/data.txt")));
    }

    @After
    public void teardown()
        throws IOException
    {
        if (in != null)
        {
            in.close();
        }

        in = null;
    }

    @Test
    public void testFoo()
        throws IOException
    {
        String line = in.readLine();

        assertThat(line, notNullValue());
    }
}

Sie müssen lediglich sicherstellen, dass sich die betreffende Datei im Klassenpfad befindet. Wenn Sie Maven verwenden, legen Sie die Datei einfach in src / test / resources ab, und Maven nimmt sie beim Ausführen Ihrer Tests in den Klassenpfad auf. Wenn Sie so etwas häufig tun müssen, können Sie den Code, der die Datei öffnet, in eine Oberklasse einfügen und Ihre Tests davon erben lassen.

Joey Gibson
quelle
Vielen Dank, dass Sie tatsächlich gesagt haben, wo sich die Datei befinden soll, und nicht nur, wie sie geöffnet werden soll!
Vince
1

Sie können versuchen:

String myResource = IOUtils.toString(this.getClass().getResourceAsStream("yourfile.xml")).replace("\n","");
Guido Celada
quelle
1

Wenn Sie eine Testressourcendatei als Zeichenfolge mit nur wenigen Codezeilen und ohne zusätzliche Abhängigkeiten laden möchten, ist dies der Trick:

public String loadResourceAsString(String fileName) throws IOException {
    Scanner scanner = new Scanner(getClass().getClassLoader().getResourceAsStream(fileName));
    String contents = scanner.useDelimiter("\\A").next();
    scanner.close();
    return contents;
}

"\\ A" entspricht dem Beginn der Eingabe und es gibt immer nur einen. Dadurch wird der gesamte Dateiinhalt analysiert und als Zeichenfolge zurückgegeben. Das Beste ist, dass keine Bibliotheken von Drittanbietern (wie IOUTils) erforderlich sind.

gMännlich
quelle