如何在构造函数中使用 Moles?

7

我有一个如下所示的类:

public class Product : IProduct
{
    static private string _defaultName = "default";
    private string _name;
    private float _price;
    /// Constructor
    public Product()
    {
        _price = 10.0F;
    }
    public void ModifyPrice(float modifier)
    {
        _price = _price * modifier;
    }  

我希望ModifyPrice在特定值下什么也不做,但我同时也想调用将价格设置为10的构造函数。我尝试了以下代码:

var fake = new SProduct() { CallBase = true };
var mole = new MProduct(fake)
    {
        ModifyPriceSingle = (actual) =>
        {
            if (actual != 20.0f)
            {
                MolesContext.ExecuteWithoutMoles(() => fake.ModifyPrice(actual));
            }
        }
    };
MProduct.Constructor = (@this) => (@this) = fake;

即使使用正确的构造函数对fake进行了良好的初始化,我也无法将其分配给@this。我还尝试了类似于以下的操作:

MProduct.Constructor = (@this) => { var mole = new MProduct(@this)... };

但是这一次我不能调用我的构造函数。我该怎么办?
2个回答

5

您不需要模拟构造函数,Product类的无参构造函数已经实现了您想要的功能。

Product添加一些调试输出。

public class Product
{
    private float _price;
    public Product()
    {
        _price = 10.0F;
        Debug.WriteLine("Initializing price: {0}", _price);
    }
    public void ModifyPrice(float modifier)
    {
        _price = _price*modifier;
        Debug.WriteLine("New price: {0}", _price);
    }
}

仅模拟ModifyPrice方法。

[TestMethod]
[HostType("Moles")]
public void Test1()
{
    // Call a constructor that sets the price to 10.
    var fake = new SProduct { CallBase = true };
    var mole = new MProduct(fake)
    {
        ModifyPriceSingle = actual =>
        {
            if (actual != 20.0f)
            {
                MolesContext.ExecuteWithoutMoles(() => fake.ModifyPrice(actual));
            }
            else
            {
                Debug.WriteLine("Skipped setting price.");
            }
        }
    };
    fake.ModifyPrice(20f);
    fake.ModifyPrice(21f);
}

请查看调试输出以确认一切正常:
    初始化价格:10
    跳过设置价格。
    新价格:210
顺便说一下,您不需要在此处使用存根。
var fake = new SProduct { CallBase = true };

创建一个Product实例就足够了。
var fake = new Product();

更新:使用AllInstances类可以轻松地模拟单个方法,如下所示。

MProduct.Behavior = MoleBehaviors.Fallthrough;
MProduct.AllInstances.ModifyPriceSingle = (p, actual) =>
{
    if (actual != 20.0f)
    {
        MolesContext.ExecuteWithoutMoles(() => p.ModifyPrice(actual));
    }
    else
    {
        Debug.WriteLine("Skipped setting price.");
    }
};

// Call the constructor that sets the price to 10.
Product p1 = new Product();
// Skip setting the price.
p1.ModifyPrice(20f);
// Set the price.
p1.ModifyPrice(21f);

呃,你没理解我的问题。你的例子有好处。但是,我需要一个调用原始方法的 Product 模拟对象,除了 ModifyPrice 方法。这就是为什么我需要 CallBase = True(用于存根)或 InstanceBehavior = MoleBehaviors.FallThrough(用于 Mole)。此外,这是最重要的一点,我想把所有未来的 Product 实例都换成我的模拟对象!这就是为什么我需要模拟构造函数的原因。 - Jeco
1
@Jeco,我可能又误解了你的意思,但是看起来你可以通过使用AllInstances类来实现你想要的功能。 - Gebb
仍然是一个好答案。对于我的不完整的示例,我感到抱歉,我总是有其他的想法。我正在将几个模拟框架与 Moles 进行比较,因此我尝试研究所有可能性。用 Moles 淹没对象的所有未来实例似乎是一个好主意(我试图检查所有方法调用,但相比于“NonImplementedException”,它代表了太多的“AllInstances”)。我曾经拼命地尝试使用构造函数来执行“@this=aMole”...但正如 Moles 手册所说,它确实是一个隔离框架而不是一个模拟框架。感谢您的回答。 - Jeco

0
MProduct.Behavior = MoleBehaviors.Fallthrough;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接