2012-02-17 13 views
9

Testuję strumień wyjściowy w java, jak poniżej.Testowanie wyjścia output.write (<String>) bez tworzenia pliku

Writer outputStream = getOutputStream(fileName); 
    if(outputStream != null) { 
     try { 
      outputStream.write(inputText); 
     } 
     finally { 
      outputStream.close(); 
     } 
    } 
    else { 
     throw new IOException("Output stream is null"); 
    } 

Jestem napisać test Mockito jak poniżej

public void testFileWrite() throws IOException { 
    when(testObj.getOutputStream(outputFileNameValidValue)).thenReturn(outputStreamMock); 
    doNothing().when(outputStreamMock).write(Matchers.anyString()); 
    doNothing().when(bufferedReaderMock).close(); 

    testObj.write(outputFileNameValidValue, reveredFileInput); 

    verify(outputStreamMock).write(Matchers.anyString()); 
    verify(outputStreamMock).close(); 
} 

Problem jest podczas tworzenia OutputStreamWriter(new FileOutputStream(filename)) plik fizyczny na dysku jest tworzony.

Czy możemy przetestować Outputstream.write bez pisania pliku na dysku?

Dzięki Anand

+1

Proszę o wyjaśnienie - skąd utworzyć 'OutputStreamWriter' - nie widzę go w kodzie. Zgaduję, że jest w 'getOutputStream' - z wyjątkiem tego, że utworzyłeś tę metodę. Musisz opublikować cały swój kod, jeśli chcesz, aby ludzie dobrze Ci pomogli. Również 'getOutputStream' powinien prawdopodobnie zostać wywołany czymś innym (może' makeWriter'), ponieważ nie otrzymuje 'OutputStream'. –

+0

W metodzie getOutputStream. Powód, dla którego przeniosłem to do metody z nadzieją, że mockito nie uruchomi mitu i nie zwróci drwin. ale jestem w błędzie. – Anand

+0

Po przejrzeniu google i przeczytaniu kilku dokumentów okazało się, że PowerMock może to łatwo zrobić. Z requireNew lub używając suppressConstructor i Whitebox.setInsternalState. Testowanie takich rzeczy za pomocą PowerMocka jest bardzo łatwe. Dziękuję wszystkim za komentarze i odpowiedzi ..pozdrowienia, Anand Barhate – Anand

Odpowiedz

9

Można użyć ByteArrayOutputStream który zapisuje dane w pamięci. Możesz to przeczytać przy pomocy ByteArrayInputStream.

Alternatywą jest napisanie oczekiwanego strumienia OutputStream, który ulegnie awarii zaraz po próbie zapisu niepoprawnego bajtu. Może to być pomocne, aby zobaczyć dokładnie, gdzie/dlaczego test kończy się niepowodzeniem.

+0

Ok .. więc użyj ByteArrayOutputStream do napisania, a ostatecznie będę musiał użyć writeTo, aby napisać do pliku? Ale wcześniej czy później napotkam ten sam problem, prawda? XXStreamWriter będzie musiał napisać plik i to jest ten fragment, którego chcę uniknąć za pomocą Mockito. – Anand

+1

Nie rozumiem. Dlaczego miałbyś pisać do pliku? –

0

Powinieneś wymyślić swój numer getOutputStream: powinien powrócić z fałszywego obiektu strumienia wyjściowego. Inwokacja new FileOutputStream rzeczywiście tworzy plik na dysku.

Teoretycznie możesz sam wykpić system plików, ale jest on o wiele bardziej skomplikowany.

A BTW if(outputStream != null) jest zbędny: strumień nigdy nie może być pusty. Jeśli nie można go utworzyć, metoda powinna wyrzucić wyjątek. To nie jest C, to jest Java. :)

+0

Właściwie to właśnie zrobiłem \t \t kiedy (testObj.getOutputStream (outputFileNameValidValue)). ThenReturn (outputStreamMock); , ale gdy zadzwonię pod numer \t \t testObj.write (outputFileNameValidValue, reveredFileInput); nadal będzie pisać pusty ciąg do pliku. Wygląda więc na to, że będę musiał kpić z systemu plików, aby uniknąć tworzenia pliku na dysku. – Anand

+0

jeśli (outputStream! = Null) to się zgadza. Jestem przyzwyczajony do defensywnego programowania :) – Anand

0

Powinieneś mieć wyśmiewane getOutputStream(String) zwrócenie java.io.StringWriter, a następnie możesz potwierdzić, że oczekiwana treść została zapisana.

public void testFileWrite() throws IOException { 
    StringWriter writer = new StringWriter(); 
    when(testObj.getOutputStream(outputFileNameValidValue)).thenReturn(writer); 

    testObj.write(outputFileNameValidValue, reveredFileInput); 

    assertEquals(reveredFileInput, writer.toString()); 

    verify(writer).close(); 
} 
1

Jak już zasugerowano, należy wstrzykiwać wyszydzony wynik w testowanej klasie. Ponieważ testowana klasa potrzebuje strumienia OutputStream, który zapisuje dany plik, będziesz musiał wstrzyknąć mocny OutputStreamFactory do testowanej klasy.

Mam ten kod dla ciebie, która jest w pełni autonomiczny:

import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mock; 
import org.mockito.runners.MockitoJUnitRunner; 

import java.io.IOException; 
import java.io.OutputStream; 

import static org.mockito.Mockito.verify; 
import static org.mockito.Mockito.when; 

@RunWith(MockitoJUnitRunner.class) 
public class Test9328173 { 

    private ClassUnderTest testObj; 

    @Mock 
    private OutputStreamFactory factory; 

    @Mock 
    private OutputStream stream; 

    @Before 
    public void setUp() throws Exception { 
     testObj = new ClassUnderTest(); 
     testObj.factory = factory; 
    } 

    @Test 
    public void testFileWrite() throws Exception { 
     when(factory.create("filename")).thenReturn(stream); 

     testObj.write("filename", new byte[]{1, 2, 3}); 

     verify(stream).write(new byte[]{1, 2, 3}); 
     verify(stream).close(); 
    } 

    private class ClassUnderTest { 

     private OutputStreamFactory factory; 

     public void write(String filename, byte[] content) throws IOException { 
      OutputStream stream = factory.create(filename); 
      try { 
       stream.write(content); 
      } finally { 
       stream.close(); 
      } 
     } 
    } 

    private interface OutputStreamFactory { 

     OutputStream create(String filename); 
    } 
} 
+0

Rzeczywiście. Argument ustawiający/konstruktora/adnotacja @Inject może być nieco łatwiejsza niż fabryka, ale jest to sposób sprawdzenia, czy strumień otrzymuje właściwe instrukcje. – avandeursen

Powiązane problemy