Question

I have a class like this:

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

I want ModifyPrice to do nothing for a specific value, but I also want to call the constructor that set the price to 10. I tried something like this:

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;

But even if fake is well-initialized with the good constructor, I can't assign it to @this. I also try something like

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

But this time I cannot call my constructor. How am I supposed to do?

Was it helpful?

Solution

You don't need to mock the constructor, the parameterless constructor of the Product class already does what you want.

Add some debugging output to 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);
    }
}

Mock only the ModifyPrice method.

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

See the debug output to confirm everything works as expected:

    Initializing price: 10
    Skipped setting price.
    New price: 210

By the way, you don't need to use the stub here,

var fake = new SProduct { CallBase = true };

creating an instance of Product will suffice.

var fake = new Product();

Update: Mocking a single method can be achieved with the AllInstances class like this

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

OTHER TIPS

MProduct.Behavior = MoleBehaviors.Fallthrough;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top