I figured the first hurdle to tackle in proving that we can use PostSharp to bend assemblies to our unit testing wills was to get rid of the need to decorate the targets of our mocking desires with attributes. I spent some time going over the documentation, browsing the forums, and looking through samples. Gael pretty much told me in the comments to my previous post to look into ICustomAttributeProvider and CompoundAttribute. I tried and failed to implement ICustomAttributeProvider; I think I don't quite understand how a PS plugin works yet. I thought going through Ruurd Boeke's examples would be enlightening... no such luck. So, instead of doing the smart thing and actually asking for help, I'm going to continue to waste time trying to figure it out on my own.
Eventually I'll get fed up and ask for some help, but in the meantime I need to make some progress somewhere in this experiment. I might as well take what I have done and at least build out some real functionality. This brings up a whole slew of interesting decisions I need to make:
- How should I structure the solution? I'm going to put any serious decisions this off until I gain better understanding of the way PS works, the licensing issues, what it is I actually want to accomplish, whether or not it's feasible, etc. I'm making a note now that the structure of the solution is going to drastically change.
- What should the API look like? Do I support multiple models for constructing unit tests (Arrange/Act/Assert and/or Record/Replay)? How do I initialize the mocks? What threading considerations do I need to make?
- How do I test? I plan on using TDD, but testing a framework used for testing seems to throw me into some sort of backwards meta-testing scenario that just feels weird.
As it stands right now in my very simple implementation, the data about the calls that need to be faked, their arguments, and the faked return values are stored in static fields of the Expect class. In order for tests to be atomic, independent units, these fields need to be reset for each test. The requirement is simple, but how do we write an individual test to test this functionality? I don’t know either. What I ended up with was this:
[Test]
public void Will_Get_Person_From_Mocked_Call()
{
var ryan = new Person { Id = 11, Name = "Ryan" };
// Set the expectation for the dao call
Expect.Call(() => PersonDao.GetPerson(0), ryan);
// Note that we don't care about the person id argument
var commandUnderTest = new PersonGetCommand();
var resultingPerson = commandUnderTest.Execute();
Assert.That(resultingPerson == ryan);
}
[Test]
public void Wont_Get_Person_From_Mocked_Call()
{
var commandUnderTest = new PersonGetCommand();
var resultingPerson = commandUnderTest.Execute();
Assert.That(resultingPerson.Id != 11);
}
These two tests work together to signal whether or not the Expectations are being correctly discarded at the end of a test/before the next test. If the second test fails, they aren’t. So I started with this, wrote some crappy code in the Expect class, and ended up adding these setup and teardown methods to the TestFixture:
[SetUp]
public void InitializeMockFramework()
{
Expect.Initialize();
}
[TearDown]
public void UnloadMockFramework()
{
Expect.UnLoad();
}
Don’t panic… I know this is ugly, especially considering what must be on the other side of Initialize and UnLoad, but this is strictly to illustrate a point – the whole fixture together functions as a single unit. Not ideal, but it’s the best solution I can come up with at the moment to test testing. It allows me to refactor the Expect class and verify that I haven’t broken functionality.
(Side thought: I’m thinking I should take a second look at that XUnit Test Patterns book; I labeled it ‘boring’ the first time I skimmed through it.)
Comments