2011-10-27 40 views
7

Trong khi làm việc với javascript sử dụng dịch vụ REST rộng rãi - bao gồm sử dụng các từ vựng như GET, PUT, POST, DELETES, v.v. Tôi đã tìm thấy nó khó khăn để giả lập phía máy chủ để phát triển phía trước kết thúc có thể đi trên một cách độc lập (của kết thúc trở lại).Làm thế nào để giả lập một cuộc gọi REST phức tạp từ phía máy chủ?

Nó cũng rất hữu ích để đôi khi thu thập dữ liệu đa bước, vì vậy chúng tôi có thể giúp tái tạo toàn bộ chuỗi của REST thậm chí (hoặc lỗi liên quan đến việc kết thúc trước đó được kích hoạt từ các dây chuyền)

gì cụ thể tôi sử dụng để mô phỏng các cuộc gọi REST, đặc biệt là các cuộc gọi nhà nước? (ví dụ: nếu tôi thực hiện PUT trên một số tài nguyên, tôi dự kiến ​​GET tiếp theo sẽ thay đổi bằng cách nào đó)

Tôi đã thử SOAPUI 4.0.1 và REST bị bỏ qua là đáng thất vọng. Thêm vào đó, nhu cầu của tôi là vượt quá trạng thái đơn lẻ (mà bất kỳ ai cũng có thể làm với một tệp .json tĩnh). Tôi cần phải làm kiểu chuyển đổi trạng thái của mocks; làm việc với tiêu đề Phạm vi nội dung sẽ là tốt nhất.

Bất kỳ ai?

Trả lời

2

Tôi thực sự đã kết thúc việc tạo Java REST Mock Engine của riêng mình về cơ bản có thể giả lập bất kỳ phản hồi nào. Miễn là bạn có thể thủ công hoặc cắt dán một tệp văn bản mô phỏng toàn bộ phản hồi http, bạn có thể sử dụng giải pháp của tôi để thử dịch vụ.

Đây servlet:

package com.mockrest.debug; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.util.Arrays; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import javax.servlet.GenericServlet; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 

/** 
* Servlet implementation class MockGridData 
*/ 
public class MockRest extends HttpServlet { 
    private static final long serialVersionUID = 1L; 

    /** 
    * @see HttpServlet#HttpServlet() 
    */ 
    public MockRest() { 
     super(); 
     // TODO Auto-generated constructor stub 
    } 

    @Override 
    public void service(ServletRequest req, ServletResponse res) 
      throws ServletException, IOException { 
     sub:{ 
      HttpServletRequest request = (HttpServletRequest)req; 
      HttpServletResponse response = (HttpServletResponse)res; 
      String setdata = request.getParameter("__setdata"); 
      if (setdata!=null && setdata.length()>0){ 
       System.err.println("Setting Data..."); 
       HttpSession sess = request.getSession(true); 
       String data = "/"+request.getParameter("__setdata"); 
       sess.setAttribute("data", data); 
       try{ 
        InputStream is = getServletContext().getResourceAsStream(data); 
        if (is!=null){ 
         is.close(); 
         response.getWriter().write("Successfully pointed next REST call to:"+data); 
        } 
        else{ 
         response.sendError(500, "Cannot find resource:"+data); 
        } 
       } 
       catch (IOException ioe){ 
        response.sendError(500, Arrays.deepToString(ioe.getStackTrace())); 
       } 

      } 
      else{ 
       System.err.println("Fetching Data..."); 
       HttpSession sess = request.getSession(false); 
       if (sess==null || sess.getAttribute("data")==null){ 
        response.sendError(500,"Session invalid or no Previous Data Set!"); 
       } 
       String rsrc = (String)sess.getAttribute("data"); 
       System.err.println("Resource Being used:"+rsrc); 
       InputStream is = getServletContext().getResourceAsStream(rsrc); 
       if (is!=null){ 
        String statusline = readLine(is); 
        Pattern statusPat = Pattern.compile("^HTTP/1.1 ([0-9]+) (.*)$"); 
        Matcher m = statusPat.matcher(statusline); 
        if (m!=null && m.matches()){ 
         int status = Integer.valueOf(m.group(1)); 
         response.setStatus(status, m.group(2)); 
        } 
        else{ 
         throw new ServletException("Bad input file: status line parsing failed, got this as status line:"+statusline); 
        } 
        String line; 
        Pattern httpHeaderPat = Pattern.compile("^([^:]+): (.*)$"); 
        while ((line=readLine(is))!=null){ 
         if (line.length()==0){ 
          // end of headers 
          break; 
         } 
         Matcher m2 = httpHeaderPat.matcher(line); 
         if (m2!=null && m2.matches()){ 
          response.setHeader(m2.group(1), m2.group(2)); 
         } 
        } 
        OutputStream os = response.getOutputStream(); 
        byte[] buf = new byte[1024]; 
        int size; 
        while ((size=is.read(buf))>0){ 
         os.write(buf, 0, size); 
        } 
        os.flush(); 
       } 
      } 
     } 
    } 

    private String readLine(InputStream is) throws IOException { 
     StringBuffer sb = new StringBuffer(); 
     char c; 
     while ((c=(char)is.read())!='\n'){ 
      sb.append(c); 
     } 
     if (sb.charAt(sb.length()-1) == '\r'){ 
      sb.deleteCharAt(sb.length()-1); 
     } 
     return sb.toString(); 
    } 

} 

Để thiết lập nó, đặt file phản ứng được xây dựng sẵn bên thư mục WebContent của bạn. Tôi thường kết thúc các tệp này với các tiện ích mở rộng .http.

Ví dụ init.http tệp bên dưới. Giả vờ chúng tôi đặt tập tin này bên trong một thư mục có tên data bên WebContent:

HTTP/1.1 200 OK 
Date: Wed, 26 Oct 2011 18:31:45 GMT 
Server: Microsoft-IIS/6.0 
X-Powered-By: ASP.NET 
X-AspNet-Version: 4.0.30319 
Content-Range: items 0-1/2 
Content-Length: 385 
Cache-Control: private 
Content-Type: application/json 

[ 
    { 
    "id": "249F0", 
    "field1": " Global", 
    "displaystartdate": "2007-10-20", 
    "displayenddate": "2012-10-20", 
    "status": "Major Delay", 
    "children": true 
    }, 
    { 
    "id": "962581", 
    "field2": "Europe", 
    "displaystartdate": "2007-10-20", 
    "displayenddate": "2012-10-20", 
    "status": "Major Delay", 
    "children": true 
    } 
] 

Headers phải riêng biệt với cơ thể bằng một dòng trống (không có khoảng trắng, nada). Những người quen thuộc với http sẽ nhận thấy đó là một phản ứng http thuần túy. Đây là mục đích.

Bạn có thể sử dụng công cụ này để mô phỏng bất kỳ tiêu đề http nào mà bạn muốn có phản hồi; thậm chí cho đến nay để đáp ứng với tiêu đề máy chủ khác nhau (trong ví dụ của tôi, tôi mô phỏng phản ứng giả vờ là IIS 6.0); hoặc mã trạng thái HTTP khác, v.v.

Để gọi mã từ trình duyệt/javascript của bạn; đầu tiên Thủ nó với:

http://yourserver/yourweb/MockGridData?__setdata=data/init.http 

Sau đó, trong javascript của bạn hoặc REST AJAX cuộc gọi, nếu nó đi để

http://yourserver/yourweb/MockGridData 

với bất kỳ phương pháp hoặc tham số; nó sẽ nhận được phản hồi http mà bạn đã tạo trước đây; thậm chí xuống đến Phạm vi Nội dung; Tiêu đề bộ nhớ cache; vv Nếu sau đó bạn cần cuộc gọi AJAX tiếp theo để trả lại một thứ khác, chỉ cần gọi lại __setdata. Tôi khuyên bạn nên thiết lập một vài nút để thực hiện chuyển đổi trạng thái rõ ràng trong ứng dụng web của bạn.

Giả sử tất cả mọi thứ được thiết lập, cho một chuỗi REST của mô phỏng, một nhà phát triển có thể làm:

  1. gọi

    http://yourserver/yourweb/MockGridData?__setdata=data/init.http 
    
  2. chạy một mô-đun javascript mà sẽ cho kết quả trong việc kêu gọi (ví dụ, với GET)

    http://yourserver/yourweb/MockGridData 
    
  3. nhấp vào nút sau đó thực hiện:

    http://yourserver/yourweb/MockGridData?__setdata=data/step1.http 
    
  4. chạy khác Bước javascript mà sẽ cho kết quả trong việc kêu gọi (ví dụ, với PUT)

    http://yourserver/yourweb/MockGridData 
    
  5. bấm một nút sau đó thực hiện:

    http://yourserver/yourweb/MockGridData?__setdata=data/step2.http 
    
  6. chạy khác Bước javascript điều đó sẽ dẫn đến việc gọi điện (nói, với GET)

    http://yourserver/yourweb/MockGridData 
    

    nhưng thời gian này mong đợi kết quả khác với kết quả # 4.

Điều này thậm chí nên hoạt động với phản hồi nhị phân và gzipped, nhưng tôi chưa thử nghiệm điều đó.

+0

Chúc mừng giải pháp. Khi bạn có thể, hãy đảm bảo đánh dấu câu trả lời của bạn là 'được chấp nhận' để những người khác có thể học hỏi từ bạn thành công. Chúc mừng ~ –

Các vấn đề liên quan