Given an constructor that is expected to throw an exception:
public class MyObject
{
public MyObject(String name)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
this.Initialize();
}
protected virtual void Initialize()
{
// do stuff
}
}
How would I use Machine.Fakes with Rhino (the default, and I am moving to Rhino) to mock up this class, and test that:
- It throws the expected exception
- It does not call Initialize()
With Moq, I can mock the actual MyObject class itself and set the property on the mock Callbase = true
to get it to act like a normal class.
I can then verify both that an exception was thrown, and that the method was not called with this:
// all pseudo code to prove my point of "creating an instance"
//
void when_creating_new_MyObject_with_null_Name_should_throw_Exception()
{
// arrange
Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty);
myObjectToTest.Callbase = true;
// act
Assert.Throws<ArgumentNullException>(() =>
var instance = myObjectToTest.Object;
);
}
void when_creating_new_MyObject_with_null_Name_should_not_call_Initialize()
{
// arrange
Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty);
myObjectToTest.Callbase = true;
// act
try
{
// creates an instance
var instance = myObjectToTest.Object;
}
catch {}
// assert
myObjectToTest.Verify(x => x.Initialize(), Times.Never());
}
But I am having trouble figuring out how to use MSpec w/Fakes to mock this up:
[Subject(typeof(MyObject), "when instantiating a new instance")
class with_null_Name
{
static MyObject myObjectToTest;
static Exception expectedException;
Establish context =()=>
myObjectToTest = An<MyObject>(String.Empty);
Because of; // I don't think there is anything to act on here?
It should_throw_Exception;
// how to capture exception with An<T>()?
It should_not_call_Initialize = () =>
myObjectToTest.WasNotToldTo(x => x.Initialize());
}
I do know about and use the Catch.Exception(...)
normally in my Because of
acts. But this use case doesn't seem to work with that.
Any pointers would be appreciated.
Thanks!
Disclaimer: The real-world use case is quite complex with heavy objects to inititalize that is quite expensive with cached backing members. The above code is just a simplified version.
Personally, I'm not accustomed to using mocking frameworks to mock things within the unit under test. I use mocks to break external dependencies using dependency injection. I'm by no means an expert at this, but my gut feeling is that this is too fine-grained a detail to test.
You say that your real world situation has lots of objects to initialize; couldn't you mock one or more of those objects and check that they aren't called? Or, use dependency injection to inject some fake object in which you can set a flag.
These suggestions all seem rather smelly to me. In the end, you know if you threw an exception that Initialize wasn't called. I think I understand that you're trying to ensure a bug doesn't creep in at a future edit, but are you in fact unit-testing the developer here? I personally would have thought it was sufficient to verify that an exception is thrown when bad data is supplied. I'm interested to hear any differing opinions though.