views:

55

answers:

4

I'm writing some unit tests and I need to be able to Assert whether a method has been called based upon the setup data.

E.g.

 String testValue = "1234";
 MyClass target = new MyClass();
 target.Value = testValue;

 target.RunConversion();

 // required Assertion
 Assert.MethodCalled(MyClass.RunSpecificConversion);

Then there would be a second test where testValue is null and I would want to assert that the method has NOT been called.


Update for specific test scenario:

I haev a class which represents information deserialized from XML. This class contains a number of pieces of information that I need to convert into my own classes.

The XML class is information about a person, including account info and a few phone numbers in different fields.

I have a method to create my Account class from the XML class, and methods to create the correct phone classes from the XML class. I have unit tests for each of these methods, but I'd like to test that when the account convertion is called, it runs the phone conversions as the results are actually properties of the account class.

I know I could test the properties of the account class after feeding in the correct information, however I have otehr nested properties that have further nested and testing the entire tree could become very cumbersome. I guess I could just have each level test the next level below it, but ideally I'd like to make sure the correct conversino methods are being called and the code is not being duplicated in the implementation.

+1  A: 

You can use a mocking framework like Rhino Mocks or moq. You can also use Isolation framework like Isolator to do that.

Another option is to inherit the class you want to verify against and raise a flag inside it that the method was called. Instead of the assert in your test assert against the flag. (basically it's a handrolled mock)

Example using Isolator:

Isolate.Verify.WasCalledWithAnyArguments(() => target.RunSpecificConversion());

Disclaimer - I work at Typemock

Elisha
+1 Honesty is always the best policy ;)
Daniel Elliott
+1  A: 

Without using a Mocking framework such as Moq, TypeMock, RhinoMocks that can verify your expectations, I would look at parsing the stack trace.

The MSDN documentation here should help.

Kindness,

Dan

Daniel Elliott
A: 

You want to investigate the use of mocking frameworks.

Or you can create your own fake objects to record the calls. You'll need to create an interface that the class implements.

One method I have seen of creating fakes looks like this:

interface MyInterface
{
    void Method();
}

// Real class
class MyClass : MyInterface
{
}

// Fake class for recording calls
class FakeMyClass : MyInterface
{
    public bool MethodCalled;
    public void Method()
    {
        this.MethodCalled = true;
    }
}

You then need to use some dependency injection to get this fake class used instead of the real one whilst running the tests.

Of course the issues with this is that the Fake class will only record method calls but not actually do anything real. This won't always be applicable. It works okay in a Model-View-Presenter environment.

Matt Breckon
+1  A: 

Another perspective - you might be unit testing at too low a level which can cause your tests to be brittle.

Typically, it is better to test the business requirement rather than implementation details. e.g. you run a conversion with "1234" as the input, and the conversion should reverse the input, so you expect "4321" as the output.

Don't test that you expect "1234" to be converted by a specific sequence of steps. In the future you might change the implementation details, then the test will fail even if the business requirements are still being met.

Of course your test in the question could be an actual business requirement in which case it would be correct.

The other case when you would want to do this is if invoking the conversion in the real MyClass is not suitable for a unit test, i.e. requires a lot of setup, or is time intensive. Then you will need to mock or stub it out.


Reply to question edit:

Based on your scenario, I would still be inclined to test by checking the output rather than checking for whether specific methods were called.

You could have tests with different XML inputs to ensure that the different conversion methods have to be called in order to pass the tests.

And I wouldn't rely on tests to check whether there was duplicate code, but rather would refactor away duplicate code when I came across it, and just rely on the unit tests to ensure that the code still performs the same function after refactoring.

RickL
Thanks for the comment, I'll udpate the question with my exact scenario...
ck