How to get rest-assured log into something printab

2019-04-30 00:24发布

问题:

I'm working into a method trying to change the default rest-assured log (which goes to the console) to a file using log4j.

It's a JUnit project which methods finally call to a REST facade, which have methods like this one.

 private ResponseSpecification responseSpecification(RequestSpecification requestSpecification, Matcher matcher, int statusCode) {
        ResponseSpecification responseSpecification = requestSpecification.expect().statusCode(StatusCode).body(".", is(matcher));
        if (log) {
            responseSpecification = responseSpecification.log().all();
        }
        return responseSpecification;
    }

Following the official doc, I've changed the method like this:

private ResponseSpecification responseSpecification(RequestSpecification requestSpecification, Matcher matcher, int statusCode) {
    final StringWriter writer = new StringWriter();
    final PrintStream captor = new PrintStream(new WriterOutputStream(writer), true);
    ResponseSpecification responseSpecification = requestSpecification.filter(logResponseTo(captor)).expect().statusCode(statusCode).body(".", is(matcher));
    System.out.println("writer = " + writer.toString() + " <-");
    return responseSpecification;
}

But writer.toString() prints always a void string (the old implementation works fine). Maybe I'm doing something wrong, but what? :(

I need to get something printable which can be managed by log4j, in this or other way.

Can anyone help me?

回答1:

I've just solved the problem writing this into the RestSuite.setUp() method

RestAssured.config = config().logConfig(new LogConfig(defaultPrintStream));

and keeping intact the old code.

private ResponseSpecification responseSpecification(RequestSpecification requestSpecification, Matcher matcher, int statusCode) {
    ResponseSpecification responseSpecification = requestSpecification.expect().statusCode(StatusCode).body(".", is(matcher));
    if (log) {
        responseSpecification = responseSpecification.log().all();
    }
    return responseSpecification;
}

I hope it can help to someone in a future.



回答2:

Might be useful too: Here a class which redirects the restAssured log() calls to a supplied logger:

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import org.slf4j.Logger;

/**
 * A wrapper class which takes a logger as constructor argument and offers a PrintStream whose flush
 * method writes the written content to the supplied logger (debug level).
 * <p>
 * Usage:<br> 
 * initializing in @BeforeClass of the unit test:
 * <pre>
 *          ToLoggerPrintStream loggerPrintStream = new ToLoggerPrintStream( myLog );
 *          RestAssured.config = RestAssured.config().logConfig(
 *                                 new LogConfig( loggerPrintStream.getPrintStream(), true ) );
 * </pre>
 * will redirect all log outputs of a ValidatableResponse to the supplied logger:
 * <pre>
 *             resp.then().log().all( true );
 * </pre>
 *
 * @version 1.0 (28.10.2015)
 * @author  Heri Bender
 */
public class ToLoggerPrintStream
{
    /** Logger for this class */
    private Logger myLog;
    private PrintStream myPrintStream;

/**
 * @return printStream
 */
public PrintStream getPrintStream()
{
    if ( myPrintStream == null )
    {
        OutputStream output = new OutputStream()
        {
            private StringBuilder myStringBuilder = new StringBuilder();

            @Override
            public void write(int b) throws IOException 
            {
                this.myStringBuilder.append((char) b );
            }

            /**
             * @see java.io.OutputStream#flush()
             */
            @Override
            public void flush()
            {
                myLog.debug( this.myStringBuilder.toString() );
                myStringBuilder = new StringBuilder();
            }
        };

        myPrintStream = new PrintStream( output, true );  // true: autoflush must be set!
    }

    return myPrintStream;
}

/**
 * Constructor
 *
 * @param aLogger
 */
public ToLoggerPrintStream( Logger aLogger )
{
    super();
    myLog = aLogger;
}


回答3:

PrintStream fileOutPutStream = new PrintStream(new File("somefile.txt"));
RestAssured.config = config().logConfig(new LogConfig().defaultStream(fileOutPutStream)); 

Use a printStream to point to a file & give a filename you want to print the log. Put the above code in your setup method for the tests & then just call log on your RequestSpecification instance as below

requestSpecification.log().all();


回答4:

One possible modification to Heri's answer - instead of StringBuilder one can use ByteArrayOutputStream - that helps if one deals with multi-language data, e.g.

// [...]
PrintStream getPrintStream() {
    if (printStream == null) {
        OutputStream output = new OutputStream() {
            ByteArrayOutputStream baos = new ByteArrayOutputStream()

            @Override
            public void write(int b) throws IOException {
                baos.write(b)
            }

            @Override
            public void flush() {
                logger.debug(this.baos.toString())
                baos = new ByteArrayOutputStream()
            }
        }
        printStream = new PrintStream(output, true)  // true: autoflush must be set!
    }
    return printStream
}
// [...]