【问题标题】:How to call delegate only once / one time with moles?如何用痣只调用一次代表/一次?
【发布时间】:2011-08-04 11:22:55
【问题描述】:

怎么可能只调用一次委托方法/一次用痣?

MyClass.AllInstances.ResultateGet = delegate { return new ResultatInfoCollection(); };

我只想调用一次“ResultateGet”方法,因为第一次没有委托的情况下 init 非常复杂。

target.UpdateResultate(); //calls delegate "ResultateGet"
//Assert some stuff
target.Verify(); //needs original function "ResultateGet" so unit test is useful

我通常对如何在调用原始函数而不是委托之前调用 moles 委托一次或特定次数感兴趣。

更新: 我找到了一种方法,这似乎有点麻烦。有更好的解决方案吗?

ResultatInfoCollection x = new ResultatInfoCollection();
MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);

【问题讨论】:

    标签: visual-studio-2010 unit-testing mocking moles pex-and-moles


    【解决方案1】:

    另外,请参阅我的回答:How to assign/opt from multiple delegates for a 'moled' method? 这提供了匿名方法内的门控逻辑示例。

    哦,好问题!我自己也遇到过这种情况。您正在寻找的称为“失败”行为(执行原始代码)。 Moles 绕道而行的匿名方法必须包含一个切换机制,在第一次调用之后就会失败。不幸的是,目前我不相信 Moles 中包含失败功能。

    您更新的解决方法正是您所需要的——调用 fallthrough 会做同样的事情。我建议添加一个标记值,doFallthrough,用于控制调用:

    bool doFallthrough = false;
    ResultatInfoCollection x = new ResultatInfoCollection();
    MyClass.AllInstances.ResultateGet = delegate { 
        if (!doFallthrough)
        {
            doFallthrough = true;
            return new ResultatInfoCollection();
        }
        MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
    };
    

    调用特定次数只需要更改哨兵值类型:

    int doFallthrough = 0;
    ResultatInfoCollection x = new ResultatInfoCollection();
    MyClass.AllInstances.ResultateGet = delegate { 
        if (++doFallthrough < 5)
            return new ResultatInfoCollection();
        MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
    };
    

    【讨论】:

      【解决方案2】:

      老问题,但由于我在搜索时发现它,我会用我的解决方案为下一个人回答。

      使用MolesContext.ExecuteWithoutMoles 调用原始函数在大多数情况下都可以正常工作,但是,如果您在此调用的下游添加任何其他函数或类,它们也不会被添加。

      给定以下类:

      public class TheClass
      {
          public int TheFunction(int input){
              return input + TheOtherFunction();
          }
      
          public int TheOtherFunction(){
              return DateTime.Now.Minutes;
          }
      }
      

      如果您使用MolesContext.ExecuteWithoutMoles 方法:

      MTheClass.AllInstances.TheOtherFunctionInt = (instance) => {
          return 5;
      };
      
      MTheClass.AllInstances.TheFunctionInt = (instance, input) =>
      {
          //do your stuff here, for example:
          Debug.WriteLine(input.ToString());
      
          var result = MolesContext.ExecuteWithoutMoles<int>(() => instance.TheFunction(input));
      
          //do more stuff, if desired    
          return result;
      };
      

      OtherFunction 的痣不会被击中,因为它是在“无痣”范围内(间接)执行的。

      但是,您可以随时添加和删除 moles 代表,以便您执行以下操作,如 Moles Documentation (p. 24) 中所述

      MTheClass.AllInstances.TheOtherFunctionInt = (instance) => {
          return 5;
      };
      
      MolesDelegates.Func<TheClass, int, int> molesDelegate = null;
      molesDelegate = (instance, input) =>
      {
          //do your stuff here, for example:
          Debug.WriteLine(input.ToString());
      
          int result = 0;
          try{
              MTheClass.AllInstances.TheFunctionInt = null;
              result = instance.TheFunction(input);
          }
          finally{
              MTheClass.AllInstances.TheFunctionInt = molesDelegate;
          }
      
          //do more stuff, if desired
      
          return result;
      };
      
      MTheClass.AllInstances.TheFunctionInt = molesDelegate;
      

      OtherFunction 痣仍然被击中。使用这种方法,您可以仅从特定方法中去除痣,而不会影响其他痣。我用过这个,它有效。我能看到的唯一问题是,如果您有递归函数,或者可能是多线程情况,它将无法工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-08
        • 2016-08-18
        • 2013-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多