使用RhinoMocks模拟参考参数

Seb*_*ier 4 c# unit-testing rhino-mocks pass-by-reference

我的代码,我有以下电话:

 string proposed=string.Empty;
 validator.IsValid(arg0, arg1, ref proposed);
Run Code Online (Sandbox Code Playgroud)

我在我的测试中存根验证器,并希望该存根改变引用的proposed字符串变量的内容.我尝试在WhenCalled-Handler中设置参数的值,但这显示没有效果.

validatorStub.Stub(x => x.IsValid(arg0, arg1, ref proposed))
                                            .IgnoreArguments()
                                            .WhenCalled(invocation =>
                                            {
                                                invocation.Arguments[2] = "123456"; 
                                            }).Throw(new ValidationException(string.Empty));
Run Code Online (Sandbox Code Playgroud)

这可能与Rhino有关吗?不幸的是,我无法编辑验证器......

编辑:感谢@FireAlkazar,我明白我必须更好地说明我的测试情况:

方法代码:

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;
   }                   
}
Run Code Online (Sandbox Code Playgroud)

测试代码:

[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);
}
Run Code Online (Sandbox Code Playgroud)

但是,当我逐步执行此操作时,我发现ValidatorStub会抛出我希望它抛出的异常,但是从不设置ref参数.


编辑: RhinoMocks的这个分支使用更新版本的Castle Core,它解决了这个问题.作者非常友好地通过Google网上论坛通知我.

Fir*_*zar 6

本案的文档Rhino Mocks 3.5 Out和Ref参数

看起来你会有类似的东西

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);
Run Code Online (Sandbox Code Playgroud)

编辑:
对你的案子进行了调查.最终结果是否定的,最新版本的Rhino Mocks(3.6)无法做到这一点.原因是模拟使用的旧版Castle.DynamycProxy中的错误.

证明:
修复bug:如果Proxied方法抛出
此修复程序,则无法接收ref&out参数,如此向Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs添加行:

bool hasByRefArguments = false;

//...

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

//...
Run Code Online (Sandbox Code Playgroud)

为Rhino.Mocks.dll添加反射器没有针对hasByRefArguments案例的额外处理(请参阅相同的文件InvocationTypeGenerator.cs).