2013-04-16 14 views
7

Chcę opisać logikę, która tworzy pliki z testami jednostkowymi. Czy można sfałszować klasę File i uniknąć rzeczywistego tworzenia plików?Czy można użyć PowerMocka do fałszywego tworzenia nowego pliku?

+0

To jest dobre pytanie. Nie zasługuje na obniżenie oceny. –

+0

Czy próbowałeś używać PowerMocka? PowerMock wyśmiewa tworzenie nowych obiektów wewnątrz metody, więc powinno działać. –

Odpowiedz

6

Makiety konstruktora, jak w tym przykładzie kodu. Nie zapomnij umieścić klasę, która wywoła "nowy plik (...)" w @PrepareForTest

package hello.easymock.constructor; 

import java.io.File; 

import org.easymock.EasyMock; 
import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.easymock.PowerMock; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({File.class}) 
public class ConstructorExampleTest { 

    @Test 
    public void testMockFile() throws Exception { 

     // first, create a mock for File 
     final File fileMock = EasyMock.createMock(File.class); 
     EasyMock.expect(fileMock.getAbsolutePath()).andReturn("/my/fake/file/path"); 
     EasyMock.replay(fileMock); 

     // then return the mocked object if the constructor is invoked 
     Class<?>[] parameterTypes = new Class[] { String.class }; 
     PowerMock.expectNew(File.class, parameterTypes , EasyMock.isA(String.class)).andReturn(fileMock); 
     PowerMock.replay(File.class); 

     // try constructing a real File and check if the mock kicked in 
     final String mockedFilePath = new File("/real/path/for/file").getAbsolutePath(); 
     Assert.assertEquals("/my/fake/file/path", mockedFilePath); 
    } 

} 
6

Nie jestem pewien, czy jest to możliwe, ale miałem taki wymóg i rozwiązałem go, tworząc interfejs FileService. Zamiast więc bezpośrednio tworzyć pliki lub uzyskiwać do nich dostęp, dodajesz abstrakcję. Wtedy możesz łatwo kpić z tego interfejsu podczas testów.

Na przykład:

public interface FileService { 

    InputStream openFile(String path); 
    OutputStream createFile(String path); 

} 

Następnie w swojej klasie przy użyciu to:

public class MyClass { 

    private FileService fileService; 

    public MyClass(FileService fileService) { 
     this.fileService = fileService; 
    } 

    public void doSomething() { 
     // Instead of creating file, use file service 
     OutputStream out = fileService.createFile(myFileName); 
    } 
} 

A w teście

@Test 
public void testOperationThatCreatesFile() { 
    MyClass myClass = new MyClass(mockFileService); 
    // Do your tests 
} 

ten sposób można nawet wyśmiewać go bez mock biblioteki.

+0

Prawidłowo. Kiedy nie możesz kpić, zawiń to w abstrakcję (interfejs), a następnie zrób to. –

+0

Ale wtedy zmieniasz prawdziwy kod, aby pomóc w testach, to jest dobre i możliwe, aby tego uniknąć z EasyMock/PowerMock – cahen

+0

@CarlosHenriqueRodriguez Tak, jesteś. I to dobrze. Pisanie kodu, który można przetestować (często) zmniejsza sprzężenie w kodzie. Powinieneś rozważyć kod testowy, aby stać się częścią twojej architektury. – NilsH

4

spróbować PowerMockito

import org.mockito.Mockito; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 


@PrepareForTest(YourUtilityClassWhereFileIsCreated.class) 
public class TestClass { 

@Test 
public void myTestMethod() { 
    File myFile = PowerMockito.mock(File.class); 
    PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(myFile); 
    Mockito.when(myFile.createNewFile()).thenReturn(true); 
} 

} 
Powiązane problemy