Could you give any suggestion on the following unit tests? How to make it more readable, maintainable and trustworthy. If it is not a problem - post some code with the suggestions.
[TestClass]
public class PropertyBagCompositeTests
{
private readonly IFixture fixture;
private readonly Mock<IPropertyBag> secondPropertyBagMock;
private readonly Mock<IPropertyBag> firstPropertyBagMock;
private readonly string propertyName;
private readonly int propertyValue;
private readonly PropertyBagComposite cut;
public PropertyBagCompositeTests()
{
fixture = new Fixture();
firstPropertyBagMock = new Mock<IPropertyBag>();
secondPropertyBagMock = new Mock<IPropertyBag>();
propertyName = Any<string>();
propertyValue = Any<int>();
cut = new PropertyBagComposite(new [] { firstPropertyBagMock.Object, secondPropertyBagMock.Object});
}
[TestMethod]
public void GetProperty_DelegatedToBags()
{
cut.PropertyGet(propertyName);
firstPropertyBagMock.Verify(x => x.PropertyGet(propertyName), Times.Once());
secondPropertyBagMock.Verify(x => x.PropertyGet(propertyName), Times.Once());
}
[TestMethod]
public void GetProperty_NoBagHasProperty_ReturnsNull()
{
object result = cut.PropertyGet(propertyName);
result.Should().BeNull();
}
[TestMethod]
public void GetProperty_OneBagHasPropety_ResturnsItsResult()
{
firstPropertyBagMock.Setup(x => x.PropertyGet(propertyName)).Returns(propertyValue);
object result = cut.PropertyGet(propertyName);
result.Should().Be(propertyValue);
}
[TestMethod]
public void GetProperty_BothBagHasPropetyWithSameValue_ResturnsItsResult()
{
firstPropertyBagMock.Setup(x => x.PropertyGet(propertyName)).Returns(propertyValue);
secondPropertyBagMock.Setup(x => x.PropertyGet(propertyName)).Returns(propertyValue);
object result = cut.PropertyGet(propertyName);
result.Should().Be(propertyValue);
}
[TestMethod]
public void GetProperty_BothBagHasPropetyWithDifferentValue_ThrowsAmbiguousResultException()
{
firstPropertyBagMock.Setup(x => x.PropertyGet(propertyName)).Returns(propertyValue);
var otherPropertyValue = Any<double>();
secondPropertyBagMock.Setup(x => x.PropertyGet(propertyName)).Returns(otherPropertyValue);
Action action = () => cut.PropertyGet(propertyName);
action.ShouldThrow<AmbiguousResultException>();
}
[TestMethod]
public void SetProperty_DelegatedToBags()
{
cut.PropertySet(propertyName, propertyValue);
firstPropertyBagMock.Verify(x => x.PropertySet(propertyName, propertyValue), Times.Once());
secondPropertyBagMock.Verify(x => x.PropertySet(propertyName, propertyValue), Times.Once());
}
[TestMethod]
public void ListProperties_ReturnsAllProperties()
{
var duplicatedPropertyName = Any<string>();
var somePropertyName = Any<string>();
var anotherPropertyName = Any<string>();
firstPropertyBagMock.Setup(x => x.ListProperties()).Returns(new[] { duplicatedPropertyName, somePropertyName });
secondPropertyBagMock.Setup(x => x.ListProperties()).Returns(new[] { anotherPropertyName, duplicatedPropertyName });
string[] result = cut.ListProperties();
result.Should().Contain(new[] { duplicatedPropertyName, somePropertyName, anotherPropertyName });
}
[TestMethod]
public void ListProperties_ReturnsDistinct()
{
var duplicated = Any<string>();
firstPropertyBagMock.Setup(x => x.ListProperties()).Returns(new[] { duplicated, Any<string>() });
secondPropertyBagMock.Setup(x => x.ListProperties()).Returns(new[] { Any<string>(), duplicated });
string[] result = cut.ListProperties();
result.Count(x => x == duplicated).Should().Be(1);
}
private T Any<T>()
{
return fixture.Create<T>();
}
}
Code Under Test:
internal class PropertyBagComposite : IPropertyBag
{
private readonly IEnumerable<IPropertyBag> propertyBags;
public PropertyBagComposite(IEnumerable<IPropertyBag> propertyBags)
{
Require.NotNull(propertyBags, "propertyBags");
this.propertyBags = propertyBags;
}
public object PropertyGet(string propertyName)
{
object result = null;
foreach (object newItem in propertyBags.Select(x => x.PropertyGet(propertyName)))
{
if (result == null)
{
result = newItem;
}
else if (newItem != null && !result.Equals(newItem))
{
throw new AmbiguousResultException();
}
}
return result;
}
public void PropertySet(string propertyName, object propertyValue)
{
propertyBags
.ForEach(x => x.PropertySet(propertyName, propertyValue));
}
public string[] ListProperties()
{
string[] result = propertyBags
.SelectMany(x => x.ListProperties())
.Distinct()
.ToArray();
return result;
}
}