2

I'm new to NMock and mocking in general. Is it possible to redefine an expectation ? In fact, I whant to mock an interface with many methods. So I decided to factorize common method expectations not to have to write them 1000 times. My issue is the following : I have a method to stub that loads a file. In most cases, the mock will do nothing for this method. So I factorized the expectation in [SetUp]

Stub.On(myMock).Method("Load").Will(Return.Value(True));

But, In a test case, I want to test that the object using the mock responds well to an exception, so I put in my test method :

Stub.On(myMock).Method("Load").Will(Throw.Exception(new FileNotFoundException()));

When I debug the test, I see the Load method is returning True. I can anderstand this, but is it possible to reset exceptation for a method or redefine it ?

boblemar
  • 1,143
  • 1
  • 10
  • 24

1 Answers1

2

I've never found a nice way to do this. I've had to use a custom action to set the value as needed for the specific call. Something like this:

[TestFixture]
public class Testing
{
    public interface IXyz
    {
        bool Load();
    }

    public class DelegateAction<T> : NMock2.IAction
    {
        private Func<T> _resultFunc;

        public void SetResultFunction(Func<T> func)
        {
            _resultFunc = func;
        }

        public DelegateAction(Func<T> resultFunc)
        {
            _resultFunc = resultFunc;
        }


        public void Invoke(Invocation invocation)
        {
            invocation.Result = _resultFunc();
        }

        public void DescribeTo(TextWriter writer)
        {
        }
    }

    private bool _result = true;
    private DelegateAction<bool> _action;

    [Test]
    public void ResetTheReturnValue()
    {
        //would be done in general setup...
        Mockery mocker = new Mockery();
        IXyz test = mocker.NewMock<IXyz>();
        _action = new DelegateAction<bool>(() => _result);
        Stub.On(test).Method("Load").Will(_action);

        //Reset for test.... - if you comment it out true is 
                       //returned as default and the test passes
        _action.SetResultFunction(() => { throw new Exception();});

        Assert.IsTrue(test.Load());
    }
}

I wouldn't normally allow the function to be set as I'd generally just want to return a different value ocasionally, which could be done by changing the field. Make sure to reset things at the end of the test.

Yes, I know this is pretty crappy and would love a better way if anyone knows of one. As an aside - if you aren't stuck with NMock you might want to take a look at something like Moq instead. I tend to have better results with it, although obviously your mileage may vary :)

Russell Troywest
  • 8,635
  • 3
  • 35
  • 40
  • Thank you... nice job ! OK, that's not as simple as I wanted... I can't use Moq because I target .net 2.0. I wanted to test Rhino mocks, but I didn't find how to download it, so I decided it's not a good choice ! – boblemar Dec 13 '11 at 12:57
  • I know - there should be a far simpler method of doing this but I suspect there just isn't. NMock2 is lacking in a number of ways in my opinion - this being one of the less important ones. Using strings for method naming etc makes it unusable as far as I'm concerned. Unfortunately the team I'm currently working with doesnt agree. – Russell Troywest Dec 13 '11 at 13:00
  • I think you can get a download of rhino mocks Here: http://builds.hibernatingrhinos.com/builds/Rhino-Mocks It's really good - I prefer Moq but would use Rhino when Moq isn't available. – Russell Troywest Dec 13 '11 at 13:12
  • Argh ! I believe I'm damned : this is where I looked for it 2 hours ago, and it didn't work ! I will try it. Thanks again. – boblemar Dec 13 '11 at 13:30