2013-02-19 9 views
5

Mam następujący przykładowy test jednostki, który próbuje sfałszować plik java.nio.file.Files, ale ta sztuczka nie działa, a kod próbuje usunąć ścieżkę próbki.Statyczna próba nie działa

@Test 
    public void testPostVisitDirectory() throws Exception { 
     Path mockedPath = Paths.get("sample path"); 
     PowerMockito.mockStatic(Files.class); 
     PowerMockito.doNothing().when(Files.class, 
       PowerMockito.method(Files.class, "delete", Path.class)); 

     DeleteDirVisitor visitor = new DeleteDirVisitor(false); 
     Assert.assertEquals("The was a problem visiting the file", 
       FileVisitResult.CONTINUE, 
       visitor.postVisitDirectory(mockedPath, null)); 
    } 

Każdy pomysł, co jest nie tak?

to jest treść, metody visitor.postVisitDirectory

[...] 
if (e == null) { 
      Files.delete(dir); 
      return FileVisitResult.CONTINUE; 
     } 
[...] 

Dzięki

+0

BTW jestem coraz NoSuchFileException. – Stainedart

Odpowiedz

4

Czy dodać

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Files.class) 

do junit klasy testowej zawierającej tę metodę?

Zobacz rozdział powermock docs, część Testy pisania.

EDIT:

Hmmm, wydaje się, że robisz wszystko dobrze. Oto co biegnę:

import java.io.IOException; 
import java.nio.file.FileVisitResult; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.nio.file.SimpleFileVisitor; 

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Files.class) 
public class TestVisitor { 
    public class PrintingVisitor extends SimpleFileVisitor<Path> { 
    @Override 
    public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException { 
     Files.delete(dir); 
     return FileVisitResult.CONTINUE; 
    } 
    } 

    @Test 
    public void testPostVisitDirectory() throws Exception { 
    final Path mockedPath = Paths.get("sample path"); 

    /* Mocking */ 
    PowerMockito.mockStatic(Files.class); 
    PowerMockito.doNothing().when(Files.class, PowerMockito.method(Files.class, "delete", Path.class)); 
    /* End Mocking */ 

    final PrintingVisitor visitor = new PrintingVisitor(); 
    Assert.assertEquals("The was a problem visiting the file", FileVisitResult.CONTINUE, visitor.postVisitDirectory(mockedPath, null)); 
    } 
} 

Jeśli komentarz sekcję oznaczoną Mocking uzyskać NoSuchFileException. Jeśli go opuszczę, test przechodzi.

Być może po zakończeniu pełnego przykładu, który powoduje błąd?

+0

Tak, jest to obecne. W tej samej klasy I rzeczywiście mają niedopałek '' 'PowerMockito.stub ( \t \t \t \t PowerMockito.method (Files.class, "deleteIfExists", Path.class)) \t \t \t \t .toReturn (true);' '' to działa – Stainedart

+0

, ale ponieważ delete zwraca void, nie mogę użyć tej samej techniki :( – Stainedart

+0

Mój problem może być bardziej skomplikowany niż ja. Z powodzeniem uruchomiłem Twój fragment w oddzielnej klasie, ale nie działa on w mojej obecnej klasie. Czy naśmiewasz rzeczy na poziomie klasy testowej? – Stainedart

1

Miałem podobny problem i okazało się, że było to związane z przygotowaniem prawidłowych zajęć.

W powyższym przykładzie testowana klasa była już w "prepareFor-Scope", ponieważ była wewnętrzną klasą klasy testowej.

Musisz dodać klasy do @PrepareForTest, które wywołują statyczne metody ... aw moim przypadku nie były wystarczające, ponieważ kod, który uzyskał dostęp do Files.delete, był wewnątrz anonimowej klasy, której nie można jawnie przygotować.

nazwałem anonimową klasę i dodać go do @PrepareForTest i wszystko działało

+0

Próbowałem dodać klasę do @PrepareForTest, ale potem wpadł na błąd stosu, z powodu błędu w najnowszym javassist: https://issues.jboss.org/browse/JASSIST-205 :-(. Oddałem się ponownie na kpiąc z Klasy plików, ale dzięki za wskazówkę! –

2

miałem podobny problem przy użyciu powermock 1.5.1 i klasy plików i podejrzewam, że ma problem statyczny szyderczy niektóre/wszystkie zajęcia jdk1.7 , chociaż nie wiem dlaczego. Sprawdziłem także wersję javassist i w tym czasie była ona najnowsza (3.18.0-GA),

Rozebrałem moją klasę w teście na samą linię plików i nadal nie działało. Postanowiłem więc spróbować sfałszować kolejną klasę statyczną, StringUtils.chop ("string"); (commons-lang3), a następnie mój test powermock zadziałał i udało mi się go zmusić do wygenerowania wyjątku od makiety.

To udowodniło mi, że zrobiłem wszystko dzięki książce i że statyczne kpiny nie działały na klasach Files, ale zrobiły to na StringUtils.

Przy okazji zmieniłem zarówno wywołania @PrepareForTest, jak i PowerMockito.mockStatic(), aby odnieść się do właściwej klasy.

W końcu zrezygnowałem z kpiny z plików. Tylko heads-up na wypadek, gdyby ktoś inny miał ten sam problem.

EDYCJA. Działa to: Od tamtej pory próbowałem tego ponownie, ponieważ potrzebowałem go w innym projekcie. Istnieje nowsza wersja PowerMock out (1.5.3), która używa zaktualizowanego javassista (3.18.1-GA), który naprawia błąd, o którym wspomniałem w mojej odpowiedzi na inny komentarz.

Mogę konsekwentnie kpić z Files do pracy dodając testowaną klasę do @PrepareForTest, a także Files teraz, nawet jeśli testowana klasa nie eksponuje metod statycznych. Nie musiałem tego robić wcześniej dla innych szyderstw. Nie wiem, dlaczego jest to potrzebne lub działa inaczej w przypadku Files.

Przykład:

public class MyTestClass { 

    public void justToTestMocking(Path path) throws IOException { 
     if (!Files.exists(path)) { 
      throw new IllegalArgumentException("I know there is a deleteIfExists() but I am just testing mocking"); 
     } 
     Files.delete(path); 
    } 
} 

A poniżej testu:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Files.class, MyTestClass.class}) 
public class MyTestClassTest { 

    @Before 
    public void setUp() { 
     mockStatic(Files.class); 

    }   

    @Test 
    public void justToTestMocking_WillDeletePath() throws IOException { 
     Path path = mock(Path.class); 
     MyTestClass test = new MyTestClass(); 

     when(Files.exists(path)).thenReturn(true); 

     test.justToTestMocking(path); 

     verifyStatic(); 
     Files.delete(path); 
    } 
}