2013-04-16 2 views

risposta

6

Mock the constructor, come in questo esempio di codice. Non dimenticare mettere la classe che richiamerà il "nuovo file (...)" nella @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

Non sono sicuro che sia possibile, ma ho avuto tale esigenza e l'ho risolto creando un'interfaccia FileService. Quindi, invece di creare/accedere direttamente ai file, aggiungi un'astrazione. Quindi puoi facilmente prendere in giro questa interfaccia nei tuoi test.

Per esempio:

public interface FileService { 

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

} 

Poi nella classe utilizzando questo:

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

E nel tuo test

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

In questo modo, si può anche prendere in giro senza alcuna finta librerie.

+0

corretto. Quando non riesci a deridere, avvolgilo in un'astrazione (interfaccia) e poi prendilo in giro. –

+0

Ma poi stai cambiando il codice reale per aiutare i test, è buono e possibile evitarlo con EasyMock/PowerMock – cahen

+0

@CarlosHenriqueRodriguez Sì, lo sei. E questa è una buona cosa. Scrivere codice che è testabile (spesso) riduce l'accoppiamento nel codice. Dovresti considerare il codice di prova come parte della tua architettura. – NilsH

4

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

}