unit-testingrhino-mocks-3.5partial-mocks

Partial mocking - expectations being ignored (Rhino Mocks)


I am trying to test a class similar to the example below:

public class Service : IService
{
    public string A(string input)
    {            
        int attemptCount = 5;
        while (attemptCount > 0)
        {
            try
            {
                return TryA(input);
            }
            catch (ArgumentOutOfRangeException)
            {
                attemptCount--;
                if (attemptCount == 0)
                {
                    throw;
                }
                // Attempt 5 more times
                Thread.Sleep(1000);                        
            }                    
        }
        throw new ArgumentOutOfRangeException();            
    }

    public string TryA(string input)
    {
    // try actions, if fail will throw ArgumentOutOfRangeException
    }
}

[TestMethod]
public void Makes_5_Attempts()
{
    //  Arrange
    var _service = MockRepository.GeneratePartialMock<Service>();
    _service.Expect(x=>x.TryA(Arg<string>.Is.Anything)).IgnoreArguments().Throw(new ArgumentOutOfRangeException());

    //  Act
    Action act = () => _service.A("");

    //  Assert
    //  Assert TryA is attempted to be called 5 times
    _service.AssertWasCalled(x => x.TryA(Arg<string>.Is.Anything), opt => opt.Repeat.Times(5));
    //  Assert the Exception is eventually thrown
    act.ShouldThrow<ArgumentOutOfRangeException>();
}

The partial mocking doesn't seem to accept my expectation. When I run the test I receive an error about the input. When I debug, I see that the actual implementation of the method is being executed instead of the expectation.

Am I doing this test correctly? According to the documentation ( http://ayende.com/wiki/Rhino%20Mocks%20Partial%20Mocks.ashx ): "A partial mock will call the method defined on the class unless you define an expectation for that method. If you have defined an expectation, it will use the normal rules for this."


Solution

  • It's is important to note that mocking frameworks like Rhinomocks, Moq and NSubstitute use a feature in .NET called DynamicProxy that dynamically generates a derived class of the mock in memory. Classes must:

    Methods must be part of the interface or made virtual so that alternate behaviors can be substituted at runtime.