boblemar
boblemar

Reputation: 1153

NMock : redefine method expectation

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 ?

Upvotes: 2

Views: 1388

Answers (1)

Russell Troywest
Russell Troywest

Reputation: 8776

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 :)

Upvotes: 2

Related Questions