2013-07-16 23 views
6

Aşağıdaki gibi bir sınıfım var;JMockit ile özel bir statik alan mı alayım?

class ClassA { 
    private static File myDir; 

    // myDir is created at some stage 

    private static String findFile(final String fileName) { 
     for (final String actualBackupFileName : myDir.list()) { 
      if (actualBackupFileName.startsWith(removeExtensionFrom(backupFile))) { 
       return actualBackupFileName; 
      } 
     } 
    } 
} 

Yani, temelde ben liste() üzerinde çağrıldığında ben benim test sınıfında tanımlayan dizeleri listesini verir, böylece Dosya sınıfını dışarı alay tarafından bu sınıf test etmek istiyorum.

Aşağıdakiler var ama şu anda çalışmıyor, muhtemelen yanlış bir şey yapıyorum - JMockit için yeni - herhangi bir yardım çok takdir! bu yüzden düzgün alay almıyorum onun benziyor -

@Mocked("list") File myDir; 

@Test 
    public void testClassA() { 
    final String[] files = {"file1-bla.txt"}; 

    new NonStrictExpectations() {{ 
     new File(anyString).list(); 
     returns(files); 
    }}; 

    String returnedFileName = Deencapsulation.invoke(ClassA.class, "findFile","file1.txt"); 

    // assert returnedFileName is equal to "file1-bla.txt" 
    } 

Ben ClassA içinde MyDir alanı için bir NullPointerException olsun yukarıdaki testi çalıştırırken?

cevap

10

JMockit (veya başka alay aracı) sahte alanlar veya değişkenler, bu o tiplerinin örneklerini almak türleri (sınıflar, arayüzler, vs.) alay etmez Test edilen kodun içinde saklanması uygun değildir. ClassA için

Örnek testi:

@Test 
public void testClassA(@Mocked File myDir) 
{ 
    new Expectations() {{ myDir.list(); result = "file1-bla.txt"; }}; 

    String returnedFileName = new ClassA().publicMethodThatCallsFindFile("file1.txt"); 

    assertEquals("file1-bla.txt", returnedFileName); 
} 

üzerinde çalışmalıdır. Doğrudan (veya private alanlarına erişerek) private yöntemlerini test etmenin kötü uygulama olarak kabul edildiğini unutmayın, bu yüzden burada kaçındım. Ayrıca, File sınıfına alay etmekten kaçınmak en iyisidir. Bunun yerine, yalnızca public yöntemlerini sınayın ve dosya sistemini alay etmek yerine gerçek dosyaları kullanın.

+0

Mükemmel, yardımınız için bir milyon teşekkür Rogerio, bu kodunuzda küçük bir değişiklik ile çalıştı - @Mocked File myDir @Mocked (yöntemleri = {"liste"}) değiştirilmek zorunda kaldı. Sanırım bu belki de, Deencapsualtion.invoke çağrısının bir noktada gerçek bir File nesnesine ihtiyaç duyması ve tüm yöntemlerin alay edilmesi bir şeyle etkileşime giriyor gibiydi. Ben yeni bir kullanıcıyım, o yüzden seni oylayamıyorum - aksi takdirde yaparım! – user2586917

+1

Harika! 'File' alay edilmesi, gerçekten de en azından JMockit'in eski sürümlerinde beklenmedik hatalara neden olabilir. Cevabı değişikliklerinle düzenledim. –

+0

@ Rogério, sahte nesne ('myDir') oluşturmanın yukarıdaki yolu, 'null' olan referansa neden olur ve myDir.list()' in bir 'NPE' ile başarısız olmasına neden olur. Bir fikrin neden? – mystarrocks

0

bu deneyin:

new Expectations {{ 
    invoke(File.class, "list", null, null); 
    returns(files); 
}} 
+1

Teşekkürler, ancak dokümanlar şunu söylüyor: Statik bir yöntemi çağırmak için çağrılar var - liste() Dosya statik değil - işe yaramaz. – user2586917

7

SetField yöntemini Deencapsulation sınıfından kullanabilirsiniz. Aşağıdaki örnek not:

Deencapsulation.setField(ClassA, "File", your_desired_value);