Mocking Reference Parameter with RhinoMocks

c#, pass-by-reference, rhino-mocks, unit-testing

Solution

Documentation for this case Rhino Mocks 3.5 Out and Ref arguments

Looks like you will have something like

validatorStub.Stub(x => x.IsValid(Arg<string>.Is.Anything, Arg<string>.Is.Anything, ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Anything(), "123456").Dummy));

string testRefValue = "";
validatorStub.IsValid("1", "2", ref testRefValue);
Assert.AreEqual("123456", testRefValue);

EDIT: Had an investigation on your case. Final result is no, can't do that in latest version of Rhino Mocks(3.6). The reason is a bug in old version of Castle.DynamycProxy, that is used by mocks.

Proof: fix bug: ref & out parameter can not received if Proxied Method throw an this fix adds lines to Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs like this:

bool hasByRefArguments = false;

//...

if (hasByRefArguments) 
{
    invokeMethodOnTarget.CodeBuilder.AddStatement(new TryStatement());
}

//...

Add in reflector for Rhino.Mocks.dll there is no extra handling for hasByRefArguments case(see same file InvocationTypeGenerator.cs).

Problem

I my code, I have the following call: ``` string proposed=string.Empty; validator.IsValid(arg0, arg1, ref proposed); ``` I stub the validator in my test and want that stub to alter the content of the referenced `proposed` string variable. I tried setting the value of the argument in the WhenCalled-Handler, but this shows no effect. ``` validatorStub.Stub(x => x.IsValid(arg0, arg1, ref proposed)) .IgnoreArguments() .WhenCalled(invocation => { invocation.Arguments[2] = "123456"; }).Throw(new ValidationException(string.Empty)); ``` Is this possible with Rhino at all? Unfortunately, I have no way of editing that validator... EDIT: Thanks to @FireAlkazar, I understood that I had to better illustrate my test situtation: Method Code: ``` public class ClassUnderTest { public string Arg0{get;set;} public string Arg1{get;set;} public IValidator Validator {get;set;} public bool Validate() { string proposal = string.Empty; try { if (Validator.IsValid(Arg0, Arg1, ref proposal)) return true; } catch (ValidationException ex) { if (!string.IsNullOrEmpty(proposal)) { // I want to test this section of code } } return false; } } ``` Test Code: ``` [TestMethod] public void Test_Validate_ValidatorProposes_ReturnsTrue() { string arg0 = "123456789"; string arg1 = "201208150030551ABC"; string prop = "123456"; ClassUnderTest testInstance = new ClassUnderTest(); testInstance.Arg0 = arg0; testInstance.Arg1 = arg1; IValidator validatorStub = MockRepository.GenerateStub<IValidator>(); validatorStub.Stub(x => x.IsValid(Arg<string>.Is.Equal(arg0), Arg<string>.Is.Equal(arg1), ref Arg<string>.Ref(Is.Anything(), prop).Dummy)) .Throw(new ValidationException(string.Empty)); testInstance.Validator = validatorStub; bool actual = testInstance.Validate(); Assert.IsFalse(actual); } ``` Still, when I step through this, I see that the ValidatorStub throws the exception i expect it to throw, but never sets the ref parameter. EDIT : This branch of RhinoMocks uses a newer version of Castle Core, which solves the issue. The author was kind enough to inform me about this via Google Groups.

Original source