Skip to content

Instantly share code, notes, and snippets.

@JulianMay
Last active October 20, 2016 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JulianMay/ef3d367a22829181e42a179fa97ce51f to your computer and use it in GitHub Desktop.
Save JulianMay/ef3d367a22829181e42a179fa97ce51f to your computer and use it in GitHub Desktop.
Assertion DSL for Rest Responses
using System;
using System.Linq;
using NUnit.Framework;
using RestSharp;
namespace ProjectName.Tests.System
{
public class CompositeResponseAssert : IResponseAssert
{
private readonly ResponseAssert[] _responses;
public CompositeResponseAssert(params IRestResponse[] responses)
{
if (responses == null) throw new ArgumentNullException("responses");
if (responses.Length < 1) throw new ArgumentException("At least 1 is needed for assertions to make sense");
_responses = responses.Select(x=>new ResponseAssert(x)).ToArray();
}
private IResponseAssert MakeAssertionForResponses(Action<ResponseAssert> assertion)
{
for(int i = 1; i <=_responses.Length;i++)
{
try
{
assertion(_responses[i - 1]);
}
catch(AssertionException assertFail)
{
throw new WrappedAssertionException(
string.Format("Assertion of response no. {0} failed:", i),
assertFail, string.Empty);
}
}
return this;
}
public IResponseAssert HasContentThatContains(string someContent)
{
return MakeAssertionForResponses(x => x.HasContentThatContains(someContent));
}
public IResponseAssert HasFollowingJsonBody(string expected, bool allowUnexpectedProperties = true, bool allowUndefinedArrayMembers = false)
{
return MakeAssertionForResponses(x => x.HasFollowingJsonBody(expected,allowUnexpectedProperties));
}
public IResponseAssert Is200Ok()
{
return MakeAssertionForResponses(x => x.Is200Ok());
}
public IResponseAssert Is400BadRequest()
{
return MakeAssertionForResponses(x => x.Is400BadRequest());
}
public IResponseAssert Is404NotFoundError()
{
return MakeAssertionForResponses(x => x.Is404NotFoundError());
}
public IResponseAssert Is405MethodNotAllowedError()
{
return MakeAssertionForResponses(x => x.Is405MethodNotAllowedError());
}
public IResponseAssert Is422UnprocessableEntity()
{
return MakeAssertionForResponses(x => x.Is422UnprocessableEntity());
}
public IResponseAssert IsNot4xxError()
{
return MakeAssertionForResponses(x => x.IsNot4xxError());
}
public IResponseAssert HasNoContentBody()
{
return MakeAssertionForResponses(x => x.HasNoContentBody());
}
public IResponseAssert HasRawContent(byte[] binary)
{
return MakeAssertionForResponses(x => x.HasRawContent(binary));
}
public IResponseAssert Is201Created()
{
return MakeAssertionForResponses(x => x.Is201Created());
}
public IResponseAssert HasExpectedHeader(string headerName, Func<string, bool> expectation)
{
return MakeAssertionForResponses(x => x.HasExpectedHeader(headerName, expectation));
}
public IResponseAssert HasContentType(string contentType)
{
return MakeAssertionForResponses(x => x.HasContentType(contentType));
}
public class WrappedAssertionException : AssertionException
{
private readonly AssertionException _ae;
public WrappedAssertionException(string messageHead, AssertionException ae, string messageTail)
: base(string.Format("{0}\r\n{1}\r\n{2}", messageHead, ae.Message, messageTail))
{
if (ae == null) throw new ArgumentNullException("ae");
_ae = ae;
}
public override string StackTrace
{
get
{
return _ae.StackTrace;
}
}
public override string Source
{
get
{
return _ae.Source;
}
set
{
_ae.Source = value;
}
}
}
}
}
I recommend writing a baseclass with factory methods for asserters, so you can do something like this:
var result = --Get IRestResponse Here--
AssertResponse(result)
.Is200Ok()
.HasFollowingJsonBody(@"
{
"ItWorks": true
}
");
using System;
namespace ProjectName.Tests.System
{
public interface IResponseAssert
{
IResponseAssert HasContentThatContains(string someContent);
IResponseAssert HasRawContent(byte[] binary);
IResponseAssert HasFollowingJsonBody(string expected, bool allowUnexpectedProperties = true, bool allowUndefinedArrayMembers = false);
IResponseAssert Is200Ok();
IResponseAssert Is201Created();
IResponseAssert Is400BadRequest();
IResponseAssert Is404NotFoundError();
IResponseAssert Is405MethodNotAllowedError();
IResponseAssert Is422UnprocessableEntity();
IResponseAssert IsNot4xxError();
IResponseAssert HasNoContentBody();
IResponseAssert HasContentType(string contentType);
IResponseAssert HasExpectedHeader(string headerName, Func<string, bool> expectation);
}
}
using System;
using System.Net;
using NUnit.Framework;
using RestSharp;
using Spectra.Hc.Tests.System.json;
using System.Collections;
using System.Linq;
namespace ProjectName.Tests.System
{
public class ResponseAssert : IResponseAssert
{
private JsonComparer _jsonComparer = new JsonComparer(); //See "JsonComparer.cs" gist
private readonly IRestResponse _response;
public ResponseAssert(IRestResponse response)
{
if (response == null)
throw new ArgumentNullException("response");
_response = response;
}
public IResponseAssert Is404NotFoundError()
{
Assert.That(_response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
return this;
}
public IResponseAssert Is405MethodNotAllowedError()
{
Assert.That(_response.StatusCode, Is.EqualTo(HttpStatusCode.MethodNotAllowed));
return this;
}
public IResponseAssert Is400BadRequest()
{
Assert.That(_response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
return this;
}
public IResponseAssert HasContentThatContains(string someContent)
{
StringAssert.Contains(someContent, _response.Content);
return this;
}
public IResponseAssert HasNoContentBody()
{
Assert.That(string.IsNullOrWhiteSpace(_response.Content), string.Format("Content was expected to be blank, but was \"{0}\"", _response.Content) );
return this;
}
public IResponseAssert Is422UnprocessableEntity()
{
var responseCode = (int)_response.StatusCode;
Assert.That(responseCode, Is.EqualTo(422));
return this;
}
public IResponseAssert IsNot4xxError()
{
var responseCode = (int)_response.StatusCode;
Assert.That(responseCode < 400, "Returned content is:\r\n {0}", _response.Content);
return this;
}
public IResponseAssert Is200Ok()
{
Assert.That(_response.StatusCode, Is.EqualTo(HttpStatusCode.OK),
string.Format("The response's StatusCode was expected to be '{0}', but was '{1}'.\r\n The content of the response was: {2}",
(int)HttpStatusCode.OK, (int)_response.StatusCode, _response.Content));
return this;
}
public IResponseAssert Is201Created()
{
Assert.That(_response.StatusCode, Is.EqualTo(HttpStatusCode.Created),
string.Format("The response's StatusCode was expected to be '{0}', but was '{1}'.\r\n The content of the response was: {2}",
(int)HttpStatusCode.Created, (int)_response.StatusCode, _response.Content));
return this;
}
/// <summary>
/// Asserts comparison between json-elements
/// Use *somestring* as wildcard (not the json-string "*somestring*", but actual invalid json-value *somestring* )
/// </summary>
/// <param name="expected"></param>
/// <param name="allowUnexpectedProperties"></param>
/// <returns></returns>
public IResponseAssert HasFollowingJsonBody(string expected, bool allowUnexpectedProperties = true, bool allowUndefinedArrayMembers = false)
{
var result = _jsonComparer.JsonDifferenceReport("content body", expected, _response.Content, allowUnexpectedProperties, allowUndefinedArrayMembers);
if (result.Report.HasUnexpectedDifferences)
{
Assert.Fail(string.Format("\r\n{0}\r\n##EXPECTED##\r\n{1}\r\n\r\n##ACTUAL##\r\n{2}", result.Report.Report(new string[0]), result.ExpectedPretty, result.ActualPretty));
}
return this;
}
public IResponseAssert HasContentType(string contentType)
{
StringAssert.AreEqualIgnoringCase(contentType, _response.ContentType);
return this;
}
public IResponseAssert HasRawContent(byte[] binary)
{
Assert.That(((IStructuralEquatable)binary).Equals(_response.RawBytes, StructuralComparisons.StructuralEqualityComparer), "The actual binary content is different from the expected");
return this;
}
public IResponseAssert HasExpectedHeader(string headerName, Func<string,bool> expectation)
{
var n = headerName.ToLowerInvariant();
var h = _response.Headers.FirstOrDefault(x => x.Name.ToLowerInvariant().Equals(n));
Assert.IsNotNull(h, string.Format("The response has no '{0}' header", n));
Assert.That(expectation(h.Value.ToString()), "The '{0}'-headers value '{1}' did not match expectation");
return this;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment