2013-07-16 12 views
6

Mam klasę podobną do poniższej;Makiety prywatne pole statyczne z JMockit?

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; 
      } 
     } 
    } 
} 

Więc w zasadzie, chciałbym przetestować tej klasy przez wyśmianie się klasa File tak, że gdy lista() jest wywoływana na to zwraca listę łańcuchów zdefiniować w klasie testowej.

Mam następujące, ale nie działa z minuty na minutę, prawdopodobnie coś oczywistego robię źle - jestem nowy w JMockit - każda pomoc jest doceniana!

@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" 
    } 

Po uruchomieniu powyższego testu otrzymuję NullPointerException dla pola mydir w ClassA - tak wygląda jej nie uzyskiwanie szydzili prawidłowo?

Odpowiedz

10

JMockit (lub jakiegokolwiek innego narzędzia szyderczy) nie makiety pola lub zmienne, to drwi rodzajów (klasy, interfejsy, itp), gdzie przypadki tych typów dostać przechowywane w testowanym kodzie nie są istotne.

Przykład test ClassA:

@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); 
} 

Powyższy powinien działać. Zauważ, że testowanie metod private bezpośrednio (lub uzyskiwanie dostępu do pól private) jest uważane za złą praktykę, więc uniknąłem tego tutaj. Poza tym najlepiej unikać kpienia z klasy File. Zamiast tego przetestuj tylko swoje metody public i użyj rzeczywistych plików zamiast wyśmiewać system plików.

+0

Wspaniale, dziękuję milion za pomoc Rogerio, działało to z małą zmianą kodu - @Mocked Plik myDir musiał zostać zmieniony na @Mocked (methods = {"list"}) Plik myDir, aby go uruchomić. Myślę, że to może dlatego, że wywołanie Deencapsualtion.invoke może wymagać prawdziwego obiektu File w pewnym momencie, a wyszydzanie wszystkich metod zdawało się ingerować w coś. Jestem nowym użytkownikiem, więc nie mogę głosować na ciebie - inaczej bym to zrobił! – user2586917

+1

Świetnie! Wyśmiewanie 'File' może rzeczywiście spowodować nieoczekiwane awarie, przynajmniej w starszych wersjach JMockit. Edytowałem odpowiedź wraz ze zmianami. –

+0

@ Rogério, powyższy sposób tworzenia symulowanego obiektu ('myDir') powoduje, że odwołanie ma wartość' null', powodując, że 'myDir.list()' kończy się niepowodzeniem z 'NPE'. Każdy pomysł, dlaczego? – mystarrocks

0

wypróbować to:

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

Dzięki, ale dokumenty mówią, że invoke jest dla wywołania metody statycznej - list() na Plik nie jest statyczny - nie wydaje się działać. – user2586917

7

Możesz użyć metody setField z klasy Deencapsulation. Zauważ przykład poniżej:

Deencapsulation.setField(ClassA, "File", your_desired_value); 
Powiązane problemy