Which unit testing approach and WHY do you prefer?
Inheritance-driven-testing
public class GivenSynchronizedDataLink : TestBase
{
internal SynchronizedDataLink Subject { get; private set; }
protected Mock<IDataLink> DataLinkFake { get; private set; }
protected Mock<IAutoReaderWriterLock> ReaderWriterFake { get; private set; }
private Fixture fixture;
protected override void Setup()
{
fixture = new Fixture();
ReaderWriterFake = new Mock<IAutoReaderWriterLock>();
DataLinkFake = new Mock<IDataLink>();
}
protected override void Given()
{
Subject = new SynchronizedDataLink(DataLinkFake.Object, () => ReaderWriterFake.Object);
}
protected T Any<T>()
{
return fixture.Create<T>();
}
}
[TestClass]
public class WhenDisposeCalled : GivenSynchronizedDataLink
{
[TestMethod]
public void ThenAquiresWriteLock()
{
ReaderWriterFake.Verify(x => x.Dispose(), Times.Once());
}
protected override void When()
{
Subject.Dispose();
}
}
[TestClass]
public class WhenDisposeCalledTwice : GivenSynchronizedDataLink
{
[TestMethod]
public void ThenAquiresWriteLockOnlyOnce()
{
ReaderWriterFake.Verify(x => x.Dispose(), Times.Once());
}
protected override void When()
{
Subject.Dispose();
Subject.Dispose();
}
}
[TestClass]
public class WhenGetMinStampGreaterThanCalled : GivenSynchronizedDataLink
{
private Mock<IDisposable> lockRealeaserMock;
private DateTime stamp;
[TestMethod]
public void ThenAquiresReadLock()
{
ReaderWriterFake.Verify(x => x.AcquireReadLock(), Times.Once());
}
[TestMethod]
public void ThenInvokesDataLink()
{
DataLinkFake.Verify(x => x.GetMinStampGreaterThan(stamp), Times.Once());
}
[TestMethod]
public void ThenReleasesReadLock()
{
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
protected override void Setup()
{
base.Setup();
lockRealeaserMock = new Mock<IDisposable>();
ReaderWriterFake.Setup(x => x.AcquireReadLock())
.Returns(lockRealeaserMock.Object);
}
protected override void Given()
{
base.Given();
stamp = Any<DateTime>();
}
protected override void When()
{
Subject.GetMinStampGreaterThan(stamp);
}
}
[TestClass]
public class WhenRemoveValuesWithArrayCalled : GivenSynchronizedDataLink
{
private Mock<IDisposable> lockRealeaserMock;
private ERemoveOptions options;
private DateTime[] stamps;
[TestMethod]
public void ThenAquiresWriteLock()
{
ReaderWriterFake.Verify(x => x.AcquireWriteLock(), Times.Once());
}
[TestMethod]
public void ThenInvokesDataLink()
{
DataLinkFake.Verify(x => x.RemoveValues(stamps, options), Times.Once());
}
[TestMethod]
public void ThenReleasesWriteLock()
{
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
protected override void Setup()
{
base.Setup();
lockRealeaserMock = new Mock<IDisposable>();
ReaderWriterFake.Setup(x => x.AcquireWriteLock())
.Returns(lockRealeaserMock.Object);
}
protected override void Given()
{
base.Given();
stamps = Any<DateTime[]>();
options = Any<ERemoveOptions>();
}
protected override void When()
{
Subject.RemoveValues(stamps, options);
}
}
[TestClass]
public class WhenRemoveValuesWithIntervalCalled : GivenSynchronizedDataLink
{
private DateTime fromIncl;
private Mock<IDisposable> lockRealeaserMock;
private ERemoveOptions options;
private DateTime tillIncl;
[TestMethod]
public void ThenAquiresWriteLock()
{
ReaderWriterFake.Verify(x => x.AcquireWriteLock(), Times.Once());
}
[TestMethod]
public void ThenInvokesDataLink()
{
DataLinkFake.Verify(x => x.RemoveValues(fromIncl, tillIncl, options), Times.Once());
}
[TestMethod]
public void ThenReleasesWriteLock()
{
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
protected override void Setup()
{
base.Setup();
lockRealeaserMock = new Mock<IDisposable>();
ReaderWriterFake.Setup(x => x.AcquireWriteLock())
.Returns(lockRealeaserMock.Object);
}
protected override void Given()
{
base.Given();
fromIncl = Any<DateTime>();
tillIncl = Any<DateTime>();
options = Any<ERemoveOptions>();
}
protected override void When()
{
Subject.RemoveValues(fromIncl, tillIncl, options);
}
}
[TestClass]
public class WhenSaveValuesCalled : GivenSynchronizedDataLink
{
private Mock<IDisposable> lockRealeaserMock;
private UniqueDescendingValueCollection values;
[TestMethod]
public void ThenAquiresWriteLock()
{
ReaderWriterFake.Verify(x => x.AcquireWriteLock(), Times.Once());
}
[TestMethod]
public void ThenInvokesDataLink()
{
DataLinkFake.Verify(x => x.SaveValues(values), Times.Once());
}
[TestMethod]
public void ThenReleasesWriteLock()
{
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
protected override void Setup()
{
base.Setup();
lockRealeaserMock = new Mock<IDisposable>();
ReaderWriterFake.Setup(x => x.AcquireWriteLock())
.Returns(lockRealeaserMock.Object);
}
protected override void When()
{
values = AnyValues();
Subject.SaveValues(values);
}
private UniqueDescendingValueCollection AnyValues()
{
return new UniqueDescendingValueCollection(new IValue[0]);
}
}
Single class
[TestClass]
public class SynchronizedDataLinkTests
{
private readonly SynchronizedDataLink cut;
private readonly Mock<IDataLink> dataLinkFake;
private readonly Fixture fixture;
private readonly Mock<IAutoReaderWriterLock> readerWriterFake;
public SynchronizedDataLinkTests()
{
fixture = new Fixture();
readerWriterFake = new Mock<IAutoReaderWriterLock>();
dataLinkFake = new Mock<IDataLink>();
cut = new SynchronizedDataLink(dataLinkFake.Object, () => readerWriterFake.Object);
}
[TestMethod]
public void Dispose_DisposesLock()
{
cut.Dispose();
readerWriterFake.Verify(x => x.Dispose(), Times.Once());
}
[TestMethod]
public void GetMinStampGreaterThan_AquiresReadLock()
{
ExecuteGetMinStampGreaterThan();
readerWriterFake.Verify(x => x.AcquireReadLock(), Times.Once());
}
[TestMethod]
public void GetMinStampGreaterThan_InvokesDataLink()
{
DateTime stamp = ExecuteGetMinStampGreaterThan();
dataLinkFake.Verify(x => x.GetMinStampGreaterThan(stamp), Times.Once());
}
[TestMethod]
public void GetMinStampGreaterThan_ReleasesReadLock()
{
var lockRealeaserMock = new Mock<IDisposable>();
readerWriterFake.Setup(x => x.AcquireReadLock())
.Returns(lockRealeaserMock.Object);
ExecuteGetMinStampGreaterThan();
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
[TestMethod]
public void RemoveValuesWithArray_AquiresWriteLock()
{
ExecuteRemoveValuesWithArray();
readerWriterFake.Verify(x => x.AcquireWriteLock(), Times.Once());
}
[TestMethod]
public void RemoveValuesWithArray_InvokesDataLink()
{
Tuple<DateTime[], ERemoveOptions> input = ExecuteRemoveValuesWithArray();
dataLinkFake.Verify(x => x.RemoveValues(input.Item1, input.Item2), Times.Once());
}
[TestMethod]
public void RemoveValuesWithArray_ReleasesWriteLock()
{
var lockRealeaserMock = new Mock<IDisposable>();
readerWriterFake.Setup(x => x.AcquireWriteLock())
.Returns(lockRealeaserMock.Object);
ExecuteRemoveValuesWithArray();
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
[TestMethod]
public void RemoveValuesWithInterval_AquiresWriteLock()
{
ExecuteRemoveValuesWithInterval();
readerWriterFake.Verify(x => x.AcquireWriteLock(), Times.Once());
}
[TestMethod]
public void RemoveValuesWithInterval_InvokesDataLink()
{
Tuple<DateTime, DateTime, ERemoveOptions> input = ExecuteRemoveValuesWithInterval();
dataLinkFake.Verify(x => x.RemoveValues(input.Item1, input.Item2, input.Item3), Times.Once());
}
[TestMethod]
public void RemoveValuesWithInterval_ReleasesWriteLock()
{
var lockRealeaserMock = new Mock<IDisposable>();
readerWriterFake.Setup(x => x.AcquireWriteLock())
.Returns(lockRealeaserMock.Object);
ExecuteRemoveValuesWithInterval();
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
[TestMethod]
public void SaveValues_AquiresWriteLock()
{
ExecuteSaveValues();
readerWriterFake.Verify(x => x.AcquireWriteLock(), Times.Once());
}
[TestMethod]
public void SaveValues_InvokesDataLink()
{
UniqueDescendingValueCollection values = ExecuteSaveValues();
dataLinkFake.Verify(x => x.SaveValues(values), Times.Once());
}
[TestMethod]
public void SaveValues_ReleasesWriteLock()
{
var lockRealeaserMock = new Mock<IDisposable>();
readerWriterFake.Setup(x => x.AcquireWriteLock())
.Returns(lockRealeaserMock.Object);
ExecuteSaveValues();
lockRealeaserMock.Verify(x => x.Dispose(), Times.Once());
}
private T Any<T>()
{
return fixture.Create<T>();
}
private UniqueDescendingValueCollection AnyValues()
{
return new UniqueDescendingValueCollection(new IValue[0]);
}
private DateTime ExecuteGetMinStampGreaterThan()
{
var stamp = Any<DateTime>();
cut.GetMinStampGreaterThan(stamp);
return stamp;
}
private Tuple<DateTime[], ERemoveOptions> ExecuteRemoveValuesWithArray()
{
var stamp = Any<DateTime[]>();
var options = Any<ERemoveOptions>();
cut.RemoveValues(stamp, options);
return new Tuple<DateTime[], ERemoveOptions>(stamp, options);
}
private Tuple<DateTime, DateTime, ERemoveOptions> ExecuteRemoveValuesWithInterval()
{
var from = Any<DateTime>();
var till = Any<DateTime>();
var options = Any<ERemoveOptions>();
cut.RemoveValues(from, till, options);
return new Tuple<DateTime, DateTime, ERemoveOptions>(from, till, options);
}
private UniqueDescendingValueCollection ExecuteSaveValues()
{
UniqueDescendingValueCollection values = AnyValues();
cut.SaveValues(values);
return values;
}
}
TestPropertyAttribute
s if you want to be able to find them quickly. – Magus Mar 20 '14 at 14:44