如何只用痣一次/一次呼叫代表?

时间:2011-08-04 11:22:55

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

如何使用moles一次/一次调用委托方法?

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);

2 个答案:

答案 0 :(得分:2)

  

此外,请参阅我的回答: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);
};

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

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

答案 1 :(得分:0)

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

使用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;
};

你对其他功能的痣不会被击中,因为它是在“无鼹鼠”范围内(间接)执行的。

但是,您可以随时添加和删除鼹鼠代表,这样您就可以执行以下操作,如Moles Documentation(第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;

其他功能摩尔仍然受到影响。使用此方法,您可以仅从特定方法中移除moling而不会影响其他痣。我用过这个,它有效。我能看到的唯一麻烦是,如果你有一个递归函数,或者可能是一个多线程的情况,它将无法工作。