Skip to content

Instantly share code, notes, and snippets.

@thefringeninja
Created May 27, 2014 16:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thefringeninja/1860325ad6dcf490795b to your computer and use it in GitHub Desktop.
Save thefringeninja/1860325ad6dcf490795b to your computer and use it in GitHub Desktop.
MessagingAcceptanceTests
public interface MessageFormatter
{
byte[] Serialize(object message);
object Deserialize(byte[] data, Type type);
}
public class NetDataContractMessageFormatter : MessageFormatter
{
private readonly NetDataContractSerializer serializer;
public NetDataContractMessageFormatter(NetDataContractSerializer serializer)
{
this.serializer = serializer;
// this is non negotiable.
serializer.AssemblyFormat = FormatterAssemblyStyle.Simple;
}
public byte[] Serialize(object target)
{
using (var stream = new MemoryStream())
{
serializer.Serialize(stream, target);
return stream.ToArray();
}
}
public object Deserialize(byte[] data, Type type)
{
using (var stream = new MemoryStream(data, false))
{
return serializer.Deserialize(stream);
}
}
}
[TestFixture]
public class MessagingAcceptanceTests
{
private IEnumerable<Assembly> Assemblies = new[]{ typeof(Message).Assembly };
[Test]
public void All_messages_are_decorated_with_data_contract()
{
var messageTypes = GetMessageTypes(Assemblies);
var badMessageTypes = (from messageType in messageTypes
where false == messageType.GetCustomAttributes(false).OfType<DataContractAttribute>().Any()
select messageType).ToArray();
var errorMessage = badMessageTypes
.Aggregate(
new StringBuilder().AppendLine("The following types were not decorated with DataContract:"),
(sb, type) => sb.AppendLine(type.FullName)).ToString();
Assert.IsEmpty(badMessageTypes, errorMessage);
}
[Test]
public void All_messages_have_a_private_parameterless_constructor()
{
var messageTypes = GetMessageTypes(Assemblies);
var badMessageTypes = (from messageType in messageTypes
where messageType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null) == null
select messageType).ToArray();
var errorMessage = badMessageTypes
.Aggregate(
new StringBuilder().AppendLine("The following types did not have a private parameterless constructor:"),
(sb, type) => sb.AppendLine(type.FullName)).ToString();
Assert.IsEmpty(badMessageTypes, errorMessage);
}
[Test]
public void All_messages_override_to_string()
{
var messageTypes = GetMessageTypes(Assemblies);
var badMessageTypes = (from messageType in messageTypes
where messageType.GetMethod("ToString").DeclaringType != messageType
select messageType).ToArray();
var errorMessage = badMessageTypes
.Aggregate(
new StringBuilder().AppendLine("The following types did not override ToString:"),
(sb, type) => sb.AppendLine(type.FullName)).ToString();
Assert.IsEmpty(badMessageTypes, errorMessage);
}
[Test]
public void All_messages_are_serializable_by_the_netdatacontract_message_formatter()
{
TestFormatter(new NetDataContractMessageFormatter(), Assemblies);
}
private IEnumerable<Type> GetMessageTypes(IEnumerable<Assembly> assemblies)
{
return from assembly in assemblies
from type in assembly.GetTypes()
where typeof (Message).IsAssignableFrom(type)
&& type.IsClass && false == type.IsAbstract
select type;
}
private void TestFormatter(MessageFormatter formatter, IEnumerable<Assembly> assemblies)
{
var messageTypes = GetMessageTypes(assemblies);
Func<object, object> safeSerialization = input =>
{
object output = null;
try
{
output = formatter.Deserialize(formatter.Serialize(input), input.GetType());
}
catch
{
}
return output;
};
var badMessageTypes = (from messageType in messageTypes
where safeSerialization(Activator.CreateInstance(messageType, true)) == null
select messageType).ToArray();
var errorMessage = badMessageTypes
.Aggregate(
new StringBuilder().Append("The following types could not be serialized by the ")
.Append(formatter.GetType().FullName)
.Append(" formatter:"),
(sb, type) => sb.AppendLine(type.FullName)).ToString();
Assert.IsEmpty(badMessageTypes, errorMessage);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment