2012-05-17 31 views
11

Potrzebuję przetestować następującą metodę bez zmiany samej metody. Metoda tworzy metodę POST na serwerze. Ale muszę zrobić przypadek testowy, który jest niezależny od serwera.Test Java Junit Żądanie HTTP POST

Testowałem podobną metodę przed przekierowaniem jej do pliku lokalnego. Ale to dawałem protokół jako plik, nazwa hosta jako localhost i port jako -1.

Mój problem polega na tym, że ta metoda wykonuje post i rzuca na HttpURLConnection i wr = new DataOutputStream (conn.getOutputStream()); nie będzie działać na lokalnym txt za pośrednictwem http.

// konstruktor

public HTTPConnector(String usr, String pwd, String protocol, 
      String hostname, int port) { 
     this.usr = usr; 
     this.pwd = pwd; 
     this.protocol = protocol; 
     this.hostname = hostname; 
     this.port = port; 

     // connect(); 
    } 

// metoda muszę przetestować

public String doPost(String reference, String data) throws IOException { 
     URL url = null; 
     HttpURLConnection conn = null; 
     BufferedReader rd = null; 
     DataOutputStream wr = null; 
     InputStream is = null; 
     String line = null; 
     StringBuffer response = null; 

     url = new URL(protocol, hostname, port, reference); 
     conn = (HttpURLConnection) url.openConnection(); 

     conn.setRequestMethod("POST"); 

     conn.setRequestProperty("Authorization", "Basic dGVzdDphc2Rm"); 
     conn.setRequestProperty("Content-Type", "application/xml"); 

     conn.setUseCaches(false); 
     conn.setDoInput(true); 
     conn.setDoOutput(true); 

     // Send response 
     wr = new DataOutputStream(conn.getOutputStream()); 
     wr.writeBytes(data); 
     wr.flush(); 
     wr.close(); 

     // Get response 
     is = conn.getInputStream(); 
     rd = new BufferedReader(new InputStreamReader(is)); 
     response = new StringBuffer(); 
     while ((line = rd.readLine()) != null) { 
      response.append(line); 
      response.append('\r'); 
     } 
     rd.close(); 
     return response.toString(); 
    } 

// przy czym sposób mogę przetestować

public String doGet(String reference) throws IOException { 
     connect(); 
     URL url = new URL(protocol, hostname, port, reference); 
     InputStream content = (InputStream) url.getContent(); 

     BufferedReader xml = new BufferedReader(new InputStreamReader(content)); 
     return xml.readLine(); 
    } 
+0

Czy spojrzałeś na użycie próbnych obiektów? – buymypies

+0

wel it doesnt idzie do wszystkiego lokalnego, więc trudno mi go przekierować. jeśli mogę znaleźć sposób na przekierowanie go do lokalnego pliku lub klasy, to mógłbym wykonać pracę, ale jedynym sposobem, jaki widzę, jest utworzenie lokalnego serwera/wątku. ale to oznacza, że ​​muszę skierować moje testy na serwer, aby uzyskać tam dane i serwer, który sam musi zostać zaprogramowany do handlu, aby zażądać, a to znacznie więcej pracy niż wydajnej. – Gabain1993

Odpowiedz

6

Oto test próbki. Zauważ, że zapewniane przeze mnie stwierdzenia są dla celów demonstracyjnych, musisz dostosować się do swoich potrzeb.

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ toTest.class, URL.class, HttpURLConnection.class }) 
public class soTest { 
    /** 
    * test response. 
    */ 
    private static final String TEST_RESPONSE = "test\nresponse"; 

    /** 
    * test data. 
    */ 
    private static final String DATA = RandomStringUtils.randomAscii(125); 

    /** 
    * test port. 
    */ 
    private static final int PORT = 8080; 

    /** 
    * test hosts. 
    */ 
    private static final String HOSTNAME = "hostname"; 

    /** 
    * test protocol. 
    */ 
    private static final String PROTOCOL = "http"; 

    /** 
    * test reference. 
    */ 
    private static final String REFERENCE = "REFERENCE"; 

    /** 
    * URL mock. 
    */ 
    private URL url; 

    /** 
    * HttpURLConnection mock. 
    */ 
    private HttpURLConnection connection; 

    /** 
    * Our output. 
    */ 
    private ByteArrayOutputStream output; 

    /** 
    * Our input. 
    */ 
    private ByteArrayInputStream input; 

    /** 
    * Instance under tests. 
    */ 
    private toTest instance; 

    @Before 
    public void setUp() throws Exception 
    { 
     this.url = PowerMockito.mock(URL.class); 
     this.connection = PowerMockito.mock(HttpURLConnection.class); 

     this.output = new ByteArrayOutputStream(); 
     this.input = new ByteArrayInputStream(TEST_RESPONSE.getBytes()); 
     this.instance = new toTest(PROTOCOL, HOSTNAME, PORT); 

     PowerMockito.whenNew(URL.class).withArguments(PROTOCOL, HOSTNAME, PORT, REFERENCE).thenReturn(this.url); 
    } 

    @Test 
    public void testDoPost() throws Exception 
    { 
     PowerMockito.doReturn(this.connection).when(this.url).openConnection(); 
     PowerMockito.doReturn(this.output).when(this.connection).getOutputStream(); 
     PowerMockito.doReturn(this.input).when(this.connection).getInputStream(); 

     final String response = this.instance.doPost(REFERENCE, DATA); 

     PowerMockito.verifyNew(URL.class); 
     new URL(PROTOCOL, HOSTNAME, PORT, REFERENCE); 

     // Mockito.verify(this.url).openConnection(); // cannot be verified (mockito limitation) 
     Mockito.verify(this.connection).getOutputStream(); 
     Mockito.verify(this.connection).setRequestMethod("POST"); 
     Mockito.verify(this.connection).setRequestProperty("Authorization", "Basic dGVzdDphc2Rm"); 
     Mockito.verify(this.connection).setRequestProperty("Content-Type", "application/xml"); 
     Mockito.verify(this.connection).setUseCaches(false); 
     Mockito.verify(this.connection).setDoInput(true); 
     Mockito.verify(this.connection).setDoOutput(true); 
     Mockito.verify(this.connection).getInputStream(); 

     assertArrayEquals(DATA.getBytes(), this.output.toByteArray()); 
     assertEquals(TEST_RESPONSE.replaceAll("\n", "\r") + "\r", response); 
    } 
} 


@Data 
public class toTest { 
    private final String protocol, hostname; 

    private final int port; 

    public String doPost(String reference, String data) throws IOException 
    { 
     // your method, not modified 
    } 
} 

zależności:

  • fotografia-Lang 2,5
  • powermock-api Mockito 1.4.11
  • powermock Moduł-junit4 1.4.11
  • JUnit 4,10
  • lombok 0.11.0 na testowanej klasie
+1

wydaje się, że jest to dobre rozwiązanie, ale pojawia się błąd i nie wiem, jak go rozwiązać, może możesz rzucić trochę światła: Typ org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner nie może zostać rozwiązany. Jest pośrednio \t odniesienia z wymaganych plików .class – Gabain1993

+0

Ta klasa jest dostarczana przez 'powermock-module-junit4', to dziwne. Powinieneś sprawdzić swoją ścieżkę klas –

5

Jeśli nie masz możliwości refaktoryzacji testowanej metody, nowatorskim podejściem byłoby wyśmiewanie się z HttpUrlConnection, której używa. Z pierwszej strony wydaje się to trudne, ponieważ HttpUrlConnection nie jest przekazywany jako parametr. Można to jednak kontrolować, kontrolując połączenie zwrócone z url.openConnection.

Jest to zarządzane przez procedurę obsługi protokołu zarejestrowaną pod numerem java.net.URL dla protokołu przekazywanego do konstruktora. Sztuką jest zarejestrowanie nowej procedury obsługi protokołu (szczegóły: Java - Registering custom URL protocol handlers).

Twoja nowa funkcja obsługi protokołu powinna zwrócić wyśmiewaną wersję HttpUrlConnection, którą możesz następnie wykorzystać w teście.