JUnit src / test / resources dizin yolunu almak için?


275

Ben src / test / kaynaklardan bir dosya yükleyebilirsiniz biliyorum:

getClass().getResource("somefile").getFile()

Ama nasıl src / test / resources dizinine tam yol alabilirim , yani bir dosya yüklemek istemiyorum, sadece dizinin yolunu bilmek istiyorum?


1
Meraktan: neden bilmek istiyorsun?
fge

3
@fge bir dosyayı yüklemek için kullanan test altındaki nesneye geçmek gerekir
Rory

5
Kaynak dizininize doğrudan dosya erişimi kötü bir fikirdir. Bir buhar üzerinde çalışmak için kodunuzu yeniden düzenleyin veya testinizin önce bir TemporaryFolder'da bir kopyasını oluşturmasını sağlayın.
Oliver Charlesworth

4
@OliverCharlesworth Geçici klasörleri kabul ediyorum ve org.junit.rules.TemporaryFolderher zaman kullanıyorum ... ama ... bilmeniz gereken test / kaynaklardan kopyalamak için, onun yolunu!
mike kemirgen

1
@mikerodent - Demek istediğim şuydu: bir giriş akışı aracılığıyla kaynak okumak ve sonra geçici bir dosyaya yazmak.
Oliver Charlesworth

Yanıtlar:


204

Sınıfla çalışmayı deneyin ClassLoader:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("somefile").getFile());
System.out.println(file.getAbsolutePath());

A ClassLoadersınıflardaki yüklemeden sorumludur. Her sınıfın a ClassLoader. Bu kod File, kaynak dizinden bir döndürür . getAbsolutePath()Onu çağırmak mutlak döndürür Path.

Javadoc for ClassLoader: http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html


34
Bu mutlaka iyi bir fikir değildir. Kaynak bir Kavanoz içindeyse, bu üzücü zamanlara yol açacaktır.
Oliver Charlesworth

1
@OliverCharlesworth Peki, kavanoz durumunda ne yapılabilir?
Anmol Singh Jaggi

@AnmolSinghJaggi - Orijinal sorunun altındaki yorumuma bakın :)
Oliver Charlesworth

maven build bu çözümü kullandığımda başarısız
firstpostcommenter

Dosya
adıyla

299

Sınıf yükleyicileri ile uğraşmanıza gerek yok. Aslında, sınıf yükleyici kaynakları bir jar arşivindeyken java.io.File nesneleri olmadığından içeri girmek kötü bir alışkanlıktır .

Maven, testleri çalıştırmadan önce geçerli çalışma dizinini otomatik olarak ayarlar, böylece şunları yapabilirsiniz:

    File resourcesDirectory = new File("src/test/resources");

resourcesDirectory.getAbsolutePath() Gerçekten ihtiyacınız olan şeyse doğru değeri döndürecektir.

src/test/dataTestlerinizin dosya sistemi üzerinden verilere erişmesini istiyorsanız bir dizin oluşturmanızı öneririz . Bu ne yaptığınızı netleştirir.


4
yeni Dosya ("src / test / resources / fileXYZ"); çalışmayacak. Bunu bir JUnit testine sokarsanız, Eclipse'den veya Maven'den.
seba.wagner

11
Maven'den gayet iyi çalışıyor. Tutulmada, test çalıştırıcısında geçerli çalışma dizinini ayarlamanız gerekir, ancak komut satırı maven bunu sizin için yapar.
Steve C

4
Ben öyle düşünmüyorum. Ve neden yapacağını sen ne Eclipse ne de Maven bir şey kurmak gerek kalmadan sadece "yeni Dosyası (getClass () getClassLoader () getResource (.." FileNameXYZ.xml ")" yapabileceğinden..
SEBA .wagner

10
Bunun yerine, derleme hizmet programınızın standartlarına neden uymuyorsunuz? Özellikle kodunuzu basitleştirdiğinde. IntelliJ veya Maven kullanarak çalışma dizini ayarlamanıza gerek yoktur. Bu en basit çözümdür, Eclipse her zamanki gibi bir acıdır.
James Watkins

2
IntelliJ 2014 sürümü için, @Steve C'nin belirttiği gibi, test yönteminin / sınıfının Çalıştır / Hata Ayıkla yapılandırmalarındaki çalışma dizinini yine de değiştirmek zorunda kaldım.
a_secenthusiast

76

Sadece PathJava 7'den kullanırım

Path resourceDirectory = Paths.get("src","test","resources");

Düzgün ve temiz!


Bu aynı kod Windows'ta çalışır mı? JavaDoc için Paths.get(...)(bana yine de) bunu olmayacağını önerir.
Steve C

@SteveC, File.separatoryol olarak kullanılacak dizeyi oluşturmak için sabiti kullanabilirsiniz
JeanValjean

1
Bunu biliyorum, ama çok çirkin. Buna karşılık, new File("src/test/resources")tüm platformlarda doğru olanı yapar.
Steve C

2
Neden sadece kullanmıyorsunuz Path resourceDirectory = Paths.get("src","test","resources");?
Navneeth

1
Hmm Paths.get("src", "test", "resources")ve Paths.get("src/test/resources")benim için Windows 10'da iyi çalışıyor. Neyi yanlış yapıyorum? =)
naXa

24

Bir bahar projesi ise, src / test / resource klasöründen dosya almak için aşağıdaki kodu kullanabiliriz .

File file = ResourceUtils.getFile(this.getClass().getResource("/some_file.txt"));

14

JUnit 4.12 ve Java8 kullanarak bir Maven3 projem var. myxml.xmlAltında denilen bir dosyanın yolunu almak için src/test/resources, ben bunu test durumu içinde yapmak:

@Test
public void testApp()
{
    File inputXmlFile = new File(this.getClass().getResource("/myxml.xml").getFile());
    System.out.println(inputXmlFile.getAbsolutePath());
    ...
}

IntelliJ IDE ile Ubuntu 14.04'te test edildi. Burada referans .


11

İçindeki tüm içerik klasöre src/test/resourceskopyalanır target/test-classes. Yani maven derlemesi sırasında test kaynaklarından dosya almak için aşağıdaki test-classesgibi klasörden yüklemelisiniz :

Paths.get(
    getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
).resolve(
    Paths.get("somefile")
).toFile()

Yıkmak:

  1. getClass().getProtectionDomain().getCodeSource().getLocation().toURI()- sana URI ver target/test-classes.
  2. resolve(Paths.get("somefile"))- giderir someFileiçin target/test-classesklasör.

Orijinal anwser alınır bu


8

@Steve C ve @ ashosborne1 tarafından sunulan seçeneklerde farklılıklar ve kısıtlamalar vardır. Onların belirtilmesi gerektiğine inanıyorum.

Ne zaman kullanabiliriz File resourcesDirectory = new File("src/test/resources");?

  • 1 Testler IDE üzerinden değil sadece maven üzerinden yapılacaktır.
  • 2.1 Testler maven veya
  • 2.2 IDE üzerinden ve sadece bir proje IDE'ye aktarılır. (“İthal” terimini kullanıyorum, çünkü IntelliJ IDEA içinde kullanılıyor. Bu işe yarayacak, IDE üzerinden test çalıştırdığınızda çalışma dizininiz projenizle aynı olacaktır.
  • 3.1 Testler maven veya
  • 3.2 IDE aracılığıyla ve birden fazla proje IDE'ye içe aktarılır (öğrenci olmadığınızda, genellikle birkaç projeyi içe aktarırsınız) ve IDE aracılığıyla testleri çalıştırmadan önce, çalışma dizini testleriniz için manuel olarak yapılandırırsınız. Bu çalışma dizini, testleri içeren içe aktarılmış projenize başvurmalıdır. Varsayılan olarak, IDE'ye aktarılan tüm projelerin çalışma dizini yalnızca bir tanesidir. Muhtemelen IntelliJ IDEAsadece bir kısıtlamadır , ancak bence tüm IDE'ler bu şekilde çalışır. Ve manuel olarak yapılması gereken bu yapılandırma hiç de iyi değil. Farklı maven projelerinde var olan, ancak tek bir büyük “IDE” projesine aktarılan çeşitli testlerle çalışarak, bizi hatırlamaya zorlar ve rahatlamanıza ve işinizden zevk almanıza izin vermez.

@ Ashosborne1 tarafından sunulan çözüm (kişisel olarak bunu tercih ederim), testleri çalıştırmadan önce yapılması gereken 2 ek gereksinim gerektirir. Bu çözümü kullanma adımlarının listesi aşağıdadır:

  • “Src / test / resources /” içinde bir test klasörü (“teva”) ve dosya (“benioku”) oluşturun:

    src / test / kaynaklar / teva / beni oku

    Dosya test klasöründe oluşturulmalıdır, aksi takdirde çalışmaz. Maven boş klasörleri yok sayar.

  • En az bir kez üzerinden proje oluşturun mvn clean install. Testler de yapacaktır. Tüm bir proje oluşturmadan sadece test sınıfınızı / yönteminizi maven üzerinden çalıştırmak yeterli olabilir. Sonuç olarak, test kaynaklarınız test sınıflarına kopyalanacaktır, işte bir yol:target/test-classes/teva/readme

  • Bundan sonra, @ ashosborne1 tarafından zaten sunulan kodu kullanarak klasöre erişebilirsiniz (Üzgünüm, bu öğe listesinin içindeki bu kodu doğru bir şekilde düzenleyemediğim için):

public static final String TEVA_FOLDER = "teva"; ... 
URL tevaUrl = YourTest.class.getClassLoader().getResource(TEVA_FOLDER); 
String tevaTestFolder = new File(tevaUrl.toURI()).getAbsolutePath();

Artık testinizi IDE üzerinden istediğiniz kadar çalıştırabilirsiniz. Temiz mvn çalışana kadar. Hedef klasörü düşecektir.

Bir test klasörü içinde dosya oluşturma ve maven'i ilk kez çalıştırma, IDE aracılığıyla testleri çalıştırmadan önce gerekli adımlar gereklidir. Bu adımlar olmadan, sadece IDE'nizde test kaynakları oluşturursanız, test yazıp yalnızca IDE ile çalıştırın, bir hata alırsınız. Testleri mvn ile yapmak test kaynaklarını hedef / test sınıfları / teva / benioku dosyasına kopyalar ve bir sınıf yükleyici için erişilebilir hale gelir.

IDE'de neden birden fazla maven projesini içe aktarmaya ihtiyacım olduğunu ve neden bu kadar karmaşık şeyleri sorabilirsiniz? Benim için temel motivasyonlardan biri: IDA ile ilgili dosyaları koddan uzak tutmak. İlk olarak IDE'mde yeni bir proje oluşturuyorum. Sahte bir projedir, bu sadece IDE ile ilgili dosyaların sahibidir. Sonra, zaten var olan maven projelerini ithal ediyorum. İçe aktarılan bu projeleri IDEA dosyalarını yalnızca orijinal sahte projemde tutmaya zorlarım. Sonuç olarak kod arasında IDE ile ilgili dosyaları görmüyorum. SVN onları görmemelidir (svn / git'i bu dosyaları yok saymak için yapılandırmayı önermeyin, lütfen). Ayrıca sadece çok uygun.


Merhaba Alexandr, ben hedef dosya / sınıflar ve src / main / kaynak Kaynak dosyası ile sorun yaşıyorum ve bu konuda sadece bir konuşma gibi görünüyor. İlk src / main / resource dosya var, derleme projesi sonra, bu dosyayı hedef / sınıflara kopyalayın. Ve bundan, getClass (). GetClassLoader (). GetResource (fileName) sadece hedef klasörde çalışırken src / main üzerinde çalışmak istiyorum. GetResource dosyasının mekanizması hakkında bir yere link verebilir misiniz? Kaynak klasörü nasıl yapılandırılır? Tks: D
Huy Hóm H Jannh

2
@Huy Hóm Hỉnh, bunu tavsiye etmem. Korkarım yanlış yöne gidersiniz.Kaynak dosyalarının bulunduğu bazı yerler vardır, yerler diğer herkes tarafından bilinir. Bu tür projelerin bakımı daha kolaydır. Sizin için bile daha kolay olacak, sadece maven projelerinin yapısını anlamanız gerekiyor. Ancak kesin olarak, varsayılan kaynak konumunu [ maven.apache.org/plugins/maven-resources-plugin/examples/…
Alexandr

@ HuyHómHỉnh, Ayrıca buradaki çözüme de bir göz atın: stackoverflow.com/questions/23289098/… Ama src / main dosyasını bir kaynak olarak yapılandırmak için ... Bundan kaçınmaya çalışın, yanlış bir şey yaptığınız anlaşılıyor.
Alexandr

hm. Neyin yanlış gittiğini açıklayabilir misiniz .gitignore? Ayrıca IDEA, testleri çalıştırırken otomatik olarak Maven'i çalıştırıyor gibi görünüyor (ve varsayılan olarak doğru çalışma dizinini ayarlıyor $MODULE_DIR$). Bundan mvn testönce manuel olarak çalıştırmaya gerek yok , her şey hem Maven hem de IDEA'dan iyi çalışıyor "src/test/resources/somefile.txt".
Alex P.

5

Kullandığım en basit ve temiz çözüm, test sınıfının adının olduğunu TestQuery1ve klasörünüzde aşağıdaki gibi bir resourcesdizin olduğunu varsayalım test:

├── java
   └── TestQuery1.java
└── resources
    └── TestQuery1
        ├── query.json
        └── query.rq

Yapılacak URI'sini almak için TestQuery1:

URL currentTestResourceFolder = getClass().getResource("/"+getClass().getSimpleName());

Dosyalardan birinin URI'sini almak için TestQuery1şunları yapın:

File exampleDir = new File(currentTestResourceFolder.toURI());
URI queryJSONFileURI = exampleDir.toURI().resolve("query.json");

1
Endişeye gerek yok, aslında yardımın için teşekkür ederim !! İyi olan şu ki cevabınızı sildiğimde, soruyu silebilirim. Evet, burada da oldukça sinirliyim ama yine de teşekkürler !! İyi akşamlar :)
Noor

1

Genel bir durumda testler için kaynak klasöründeki bir dosyayı kullanamazsınız. Bunun nedeni, kaynak klasöründeki kaynak dosyalarının bir kavanozun içinde saklanmasıdır. Yani dosya sisteminde gerçek bir yolu yok.

En basit çözüm şunlar olabilir:

  1. Kaynaklardan bir dosyayı geçici klasöre kopyalayın ve bu geçici dosyaya bir yol alın.
  2. Geçici bir yol kullanarak testler yapın.
  3. Geçici dosyayı silin.

TemporaryFolderfrom JUnit, geçici dosyalar oluşturmak ve test tamamlandıktan sonra silmek için kullanılabilir. guavaKitaplıktaki sınıflar, bir dosya formu kaynak klasörünü kopyalamak için kullanılır.

Kaynak klasöründe bir alt klasör kullanırsak, tıpkı goodbir tane gibi /, kaynak yoluna satır aralığı eklememiz gerekmediğini lütfen unutmayın .

public class SomeTest {

    @Rule
    public TemporaryFolder tmpFolder = new TemporaryFolder();


    @Test
    public void doSomethinge() throws IOException {
        File file = createTmpFileFromResource(tmpFolder, "file.txt");
        File goodFile = createTmpFileFromResource(tmpFolder, "good/file.txt");

        // do testing here
    }

    private static File createTmpFileFromResource(TemporaryFolder folder,
                                                  String classLoaderResource) throws IOException {
        URL resource = Resources.getResource(classLoaderResource);

        File tmpFile = folder.newFile();
        Resources.asByteSource(resource).copyTo(Files.asByteSink(tmpFile));
        return tmpFile;
    }

}

0

Ünite testlerinize Hazırda Bekletme modunu Bahar enjekte etmek için aşağıdakileri kullanın:

@Bean
public LocalSessionFactoryBean getLocalSessionFactoryBean() {
    LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
    localSessionFactoryBean.setConfigLocation(new ClassPathResource("hibernate.cfg.xml"));
    localSessionFactoryBean.setPackagesToScan("com.example.yourpackage.model");
    return localSessionFactoryBean;
}

Eğer yoksa hibernate.cfg.xmlsizin de mevcut src/test/resourcesklasörüne otomatik olarak içinde birine geri düşecek src/main/resourcesklasöründe.


0

File nesnenizde .getAbsolutePath () kullanın.

getClass().getResource("somefile").getFile().getAbsolutePath()

getFile return String örneği FIle değil
Almas Abdrazak

@AlmasAbdrazak GreatDantone bunun getFile()bir dosya örneği döndürdüğünü söylemez . Bunun getAbsolutePath()File nesnesinin bir örneğinde kullanıldığını söylüyor .
menteith

@menteith Koduna göre getFile () 'de getFile ()' i çağırır ve getFile () 'de getAbsolutePath ()' i çağırır, ancak getFile () String 'i döndürür ve String nesnesinde getAbsolutePath ()' i
çağıramazsınız

0

Spring ile kolayca kaynaklar klasöründen okuyabilirsiniz (ana / kaynaklar veya test / kaynaklar):

Örneğin bir dosya oluşturun: test/resources/subfolder/sample.json

@Test
public void testReadFile() {
    String json = this.readFile("classpath:subfolder/sample.json");
    System.out.println(json);
}

public String readFile(String path) {
    try {
        File file = ResourceUtils.getFile(path);
        return new String(Files.readAllBytes(file.toPath()));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

0
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.