Play 1.x機能テスト文字化けしおよび符号化問題(Encoded Question In Play 1.x FunctionalTest)

5950 ワード

機能テストをしていると見積もっていると、utf-8をコードとして統一すれば、POSTテストリクエストに漢字が付いていれば文字化けしてしまうことに気づきましたか.
{"box":[{"entityId":7,"id":7,"idea":"?????","jPAContext":{"insideTransaction":true,"jPAConfig":{"configName":"play","enabled":true,"insideTransaction":true,"jPAContext":{"$ref":".."},"jpql":{}}},"persistent":false,"type":1},{"entityId":8,"id":8,"idea":"???","jPAContext":{"$ref":"$.box[0].jPAContext"},"persistent":false,"type":5},{"idea":"???","jPAContext":{"$ref":"$.box[0].jPAContext"},"persistent":false,"type":3}],"code":"jack","entityId":1003,"id":1003,"ip":"192.168.1.122","jPAContext":{"$ref":"$.box[0].jPAContext"},"nick":"??","passwd":"jack2","persistent":true,"qqmail":"[email protected]"}

これは典型的な符号化の問題ですが、プレイを探しても設定が見つからず、デバッグで見るしかありません. 
1.ymlファイルからデータを読み込む過程で、データがまだ文字化けしていないことに気づいた.
2.第7章で言及したActionInvokerにリクエストが届いたときに、すでに文字化けしていた. 
したがって、プレイフレームワークがPOST要求をカプセル化するのは、すべての機能テストの親であるFunctionalTestにおいて、多くのPOSTメソッドが再ロードされている問題であると推測するが、その根本はこのPOST:プレイである.test.FunctionalTest.java
public static Response POST(Request request, Object url, Map parameters, Map files) {
        List parts = new ArrayList();

        for (String key : parameters.keySet()) {
            parts.add(new StringPart(key, parameters.get(key)));
        }

        for (String key : files.keySet()) {
            Part filePart;
            try {
                filePart = new FilePart(key, files.get(key));
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
            parts.add(filePart);
        }

        MultipartRequestEntity requestEntity = new MultipartRequestEntity(parts.toArray(new Part[]{}), null); 
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            requestEntity.writeRequest(baos);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        InputStream body = new ByteArrayInputStream(baos.toByteArray());
        String contentType = requestEntity.getContentType();
        Http.Header header = new Http.Header();
        header.name = "content-type";
        header.values = Arrays.asList(new String[]{contentType});
        request.headers.put("content-type", header);
        return POST(request, url, MULTIPART_FORM_DATA, body);
    }

この方法には、new StringPart()の方法があります
parts.add(new StringPart(key, parameters.get(key)));

私がついて行くと、こいつも重荷の方法だと気づいた.com.ning.http.multipart.StringPart.java
public StringPart(String name, String value, String charset)
    {
        super(name, "text/plain", charset != null ? charset : "US-ASCII", "8bit");
        if(value == null)
            throw new IllegalArgumentException("Value may not be null");
        if(value.indexOf('\0') != -1)
        {
            throw new IllegalArgumentException("NULs may not be present in string parts");
        } else
        {
            this.value = value;
            return;
        }
    }

    public StringPart(String name, String value)
    {
        this(name, value, null);
    }

コードが一目瞭然で、
super(name, "text/plain", charset != null ? charset : "US-ASCII", "8bit");

charsetがなければ、彼は「US-ASCII」をデフォルトにします!問題が発生した場合、解決方法は多くなり、StringPartでデフォルトの「UTF-8」に変更したり、POSTメソッドで「UTF-8」パラメータを1つ多く伝えたりすることができます.しかし、この2つの方法はあまり優雅ではありません.私はここで1つの方法を提供します.まず、テストクラスの親:functionを構築します.BasisTest.java
public class BasisTest extends FunctionalTest{
    public static Response POST(Object url, Map parameters) {
        return POST(newLocalRequest(), url, parameters, new HashMap());
    }
   
    public static Request newLocalRequest() {
        Request request = Request.createRequest(
            null,
            "GET",
            "/",
            "",
            null,
            null,
            null,
            null,
            false,
            80,
            "localhost",
            false,
            null,
            null
        );
        request.encoding = "utf-8";
        return request;
    }
}

FunctionalTestのPOSTクラスをカバーし、独自のRequestを構築します.この場所ではクッキーを設定することもでき、ログインブロックがある場合に機能テストを行うのに便利です.ここでは主に設定要求のencodingです.次にFunctionalTestにおけるPOST法においてStringPart構築法を3つのパラメータとしてrequestを加える.encoding.
parts.add(new StringPart(key, parameters.get(key), request.encoding));

このようにコードは生きているので、自分で設定することができます.
{"box":[{"entityId":7,"id":7,"idea":" ","jPAContext":{"insideTransaction":true,"jPAConfig":{"configName":"play","enabled":true,"insideTransaction":true,"jPAContext":{"$ref":".."},"jpql":{}}},"persistent":false,"type":1},{"entityId":8,"id":8,"idea":" ","jPAContext":{"$ref":"$.box[0].jPAContext"},"persistent":false,"type":5},{"idea":" ","jPAContext":{"$ref":"$.box[0].jPAContext"},"persistent":false,"type":3}],"code":"jack","entityId":1003,"id":1003,"ip":"192.168.1.122","jPAContext":{"$ref":"$.box[0].jPAContext"},"nick":" ","passwd":"jack2","persistent":true,"qqmail":"[email protected]"}