VCR for ServiceStack's JsonServiceClient

284 views Asked by At

The Ruby VCR library enables you to "Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests."

I'd like to create something similar using ServiceStack's JsonServiceClient, but I can't get it to work. My most recent failed attempt follows. I'd like to either make my current attempt work, or suggestions on another approach that will work.

public static class Memoization
{
    public static Func<T, TResult> AsCached<T, TResult>(this Func<T, TResult> function)
    {
        var cachedResults = new Dictionary<T, TResult>();
        string filename = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + (typeof(TResult)).Name + ".jsv";
        var serializer = MessagePackSerializer.Create<Dictionary<T, TResult>>();

        if (cachedResults.Count == 0)
        {
            ////// load cache from file
            using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
            {
                cachedResults = serializer.Unpack(fs);
            }
        }

        return (argument) =>
        {
            TResult result;
            lock (cachedResults)
            {
                if (!cachedResults.TryGetValue(argument, out result))
                {
                    result = function(argument);
                    cachedResults.Add(argument, result);


                    ////// update cache file
                    using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
                    {
                        serializer.Pack(fs, cachedResults);
                    }
                }
            }
            return result;
        };
    }

}
class MemoizeJsonClient<TResponse> : JsonServiceClient, IServiceClient, IRestClient
{
    private Func<IReturn<TResponse>, TResponse> _getCached;
    private JsonServiceClient client;

    public TResponse Get(IReturn<TResponse> request)
    {
        if (_getCached == null)
        {
            Func<IReturn<TResponse>, TResponse> func = GetImpl;
            _getCached = func.AsCached();
        }
        return _getCached(request);
    }

    private TResponse GetImpl(IReturn<TResponse> request)
    {
        return client.Get(request);
    }

    public MemoizeJsonClient(string BaseUri) {
        client = new JsonServiceClient(BaseUri);
    }
}

Called like this:

[Test]
public void TestReports2()
{
    string Host = "http://localhost:1337";
    string BaseUri = Host + "/";

    List<Options> testcases = new List<Options>();
    testcases.Add(new Options("Name", "20130815", "20130815"));

    foreach (Options options in testcases)
    {
        TransactionsReq transRequest = new TransactionsReq();
        transRequest.source = "Source";
        transRequest.name = new List<String>(new string[] { options.Name });
        transRequest.startDate = options.StartDate;
        transRequest.endDate = options.EndDate;
        MemoizeJsonClient<TransactionsReqResponse> client = new MemoizeJsonClient<TransactionsReqResponse>(BaseUri);
        List<Transaction> transactions;

        TransactionsReqResponse transResponse = client.Get(transRequest);
        transactions = transResponse.data;
    }
}

But I get the following error:

System.Runtime.Serialization.SerializationException occurred
  HResult=-2146233076
  Message=Cannot serialize type 'ServiceStack.ServiceHost.IReturn`1[ImagineServerWrapper.DTO.TransactionsReqResponse]' because it does not have any serializable fields nor properties.
  Source=MsgPack
  StackTrace:
       at MsgPack.Serialization.SerializerBuilder`1.CreateSerializer()
  InnerException: 
0

There are 0 answers