When testing in C# it's not unusual to test instances of a class. The problem we all face is having a place to initialize our objects.
- Create a field that is initialized and reset on
[TearDown]
? - Create a null field that is initialized during
[SetUp]
? - Duplicate the initialization in every
[Test]
?
All three of these are valid, and unfortunately, all three can be found in the same project and sometimes the same test!
namespace DoYourTestsLookLikeThis
{
[TestFixture]
public class InsertTearsEmoji
{
private UnitOfWork _work = new UnitOfWork();
private Mock<IArticlesService> MockArticlesService { get; set; }
[SetUp]
public void BeforeEach()
{
MockArticlesService = new Mock<IArticlesService>(_work);
}
[TearDown]
public void AfterEach()
{
// 😭😭😭
_work = new UnitOfWork();
}
[Test]
public void IndexShouldLoadPublishedArticles()
{
var controller = new ArticlesController(MockArticlesService.Object);
controller.Index();
MockArticlesService.Verify(service => service.Published(), Times.Once);
}
}
}
namespace HappyDance
{
// This allows us to call +Let+ directly
using static LetTestHelper.LetHelper;
[TestFixture]
public class ArticlesControllerTest
{
private UnitOfWork Work => Let(() => new UnitOfWork());
// We can depend on other Lets
private Mock<IArticlesService> MockArticlesService => Let(() => new Mock<IArticlesService>(Work));
// It's so easy, why not move it here too
private ArticlesController Controller => Let(() => new ArticlesController(MockArticlesService.Object);
[TearDown]
public void AfterEach()
{
// You may cry, but only once (see below 👇)
LetTestHelper.LetHelper.Flush();
}
[Test]
public void IndexShouldLoadPublishedArticles()
{
Controller.Index();
MockArticlesService.Verify(service => service.Published(), Times.Once);
}
}
}
- After each test you will need to manually flush the results. My recommendation is creating a test helper that will flush the cache on tear down.
namespace MyProject.TestHelper
{
[TestFixture]
public class TestBase
{
[TearDown]
public void Clean_LetHelper()
{
LetTestHelper.LetHelper.Flush();
}
}
}
Coming from Ruby I found instance management in C# to be, well, not fun. This is
is influenced by RSpec let
.