用于测试私有方法的非代码生成的转发填充程序

时间:2009-06-25 13:23:21

标签: .net testing reflection xunit.net internalsvisibleto

一般而言,我设计类的方式是不需要访问私有来进行测试。 InternalsVisibleTo也可以提供帮助。

但是,我目前正在处理一个代码库,它有一些区域已经依赖于[VSTS中的私有访问器机制](http://msdn.microsoft.com/en-us/library/ms184807(VS.80).aspx)(即使用VSCodeGenAccessors生成{{ 1}}具有使用反射转发的类,用于在类上调用*_Accessor成员(以及可选的private成员。)

所以我有类似的代码:

internal

(是的,充满反模式 - 但请不要射击信使)

我有很多问题:

  1. 我希望能够澄清我需要的私人资料
  2. 我不想调用对话框(是的,我是一个CRaholic)
  3. 我不想在图片中涉及代码生成
  4. 所以我希望能够将上面的代码转换为:

    ClassUnderTest target = new ClassUnderTest();
    var accessor = ClassUnderTest_Accessor.AttachShadow( target );
    accessor.PrivateMethod();
    Assert.True( accessor._privateMethodWasCalled);
    accessor.PrivateProperty = 5;
    Assert.Equal( accessor.PrivateProperty, 5);
    

    只有以下界面位于我的测试程序集中,并且没有生成代码或自定义构建步骤: -

    var target = new ClassUnderTest();
    IClassUnderTestInterface accessor = Shadow.Create<IClassUnderTestInterface>( target );
    accessor.PrivateMethod();
    Assert.True( accessor._privateMethodWasCalled);
    accessor.PrivateProperty = 5;
    Assert.Equal( accessor.PrivateProperty, 5);
    

    从那里,我可以使用CodeRush或Ctrl K M在界面上生成新的阴影方法,只需要一次击键。

    缺少的位将有一个方法interface IClassUnderTestInterface { int PrivateProperty {get; set;} bool _privateMethodWasCalled {get; } void PrivateMethod(); }   1.生成实现接口的动态代理   1.验证要包装的对象I Shadow.Create<I>( Object o)是否具有接口指示的所有成员   1. bnous:正确管理代表字段的属性转发(即`_privateMethodWasCalled'案例)

    那么,有没有人知道一个实现这样的东西的库(或者觉得无聊到写它?)

    一个明显的缺点是你不知道界面是否在运行时不能与ClassUnderTest相提并论,但这没关系,因为这只适用于测试。另外,AIUI,私有访问器机制也需要触发重新编译以不时地同步内容。

    或者有没有更好的方法我错过了? (记住我不想去内部或公共场所,并且不想重写工作代码)

    使用xUnit.net,.NET 3.5;打开使用任何动态代理库或其他

3 个答案:

答案 0 :(得分:1)

您是否看过像Moq或Rhino这样的模拟框架?在您的情况下,如果您愿意将需要测试的私有化更改为“受保护的虚拟”(这并不像内部公开那么糟糕),他们可以提供帮助。基本上,如果成员是虚拟的,那么模拟框架可以生成一个子类来记录成员被调用的内容。

答案 1 :(得分:1)

我最终绕过所有这些东西(InternalsVisibleTo,单独的测试项目,测试引用,私有访问器,MSBuild Shadow任务/ publicize.exe在构建中随机失败,使用反射访问私有)通过合并测试主要项目并制作需要从测试internal访问的任何内容。另请参阅xUnit.net Test Stripper [to remove test code embedded in binaries prior to deployment/shipping]

答案 2 :(得分:0)

这个neat trick可以使转发功能更加简洁,虽然它本质上仍然是手动的

此外,this answer涵盖了如何处理static成员(但要求CLR4在我提出要求时没有发挥作用,并且在未将InternalsVisibleTo带入的情况下不处理私有方法混合)。