1

I'm trying to unit test a method where a property is non-virtual, and there are two layers of inheritance - therefore I can not create a mock. I've created a fake, however for some reason the property value is still empty.

public class Cart {
    public string Currency { get; set; } // I'm trying to override this
}

// My fake class
public class CartFake : Cart
{
    public new string Currency {  // This should hide SomeBaseBase.Cart.Currency - but it does not
        get { return "USD"; }
        set { value = "USD"; }
    }
}


public abstract class SomeBaseBase {
    public virtual Cart Cart { get; set; }
}

public class Base : SomeBaseBase {
   public string OtherProperties { get; set; }
}

// class under test
public class SomeClassFake : Base {
    public override Cart Cart => new CartFake();


    // Then when test is running I have this
    var currency = Cart.Currency // returns "" - when debugging I see two "Currency" properties and currency gets populated with ""
}

For some reason when the test is running I see two Currency properties and var currency = gets currency "" instead of "USD"

why is that? how can I make it so that USD is populated?

EDIT:

public class CartFake : Cart
{
    public CartFake() : base()
    {
        Currency = "USD";
    }
}

For some reason line: Cart.Currency is still empty :(

BobSwanson
  • 423
  • 2
  • 5
  • 18
  • 5
    It sounds like you should revise what the `new` modifier means, basically. You are indeed *hiding* `Cart.Currency` from the perspective of a compile-time type of `CartFake`, but you're not *overriding* it, so when you refer to `Cart.Currency` in `var currency = Cart.Currency;` that doesn't know anything about `FakeCart`. – Jon Skeet Mar 10 '17 at 17:05
  • The problem is that Cart is a 3rd party library, I can not modify it. Is there any way around this? I've tried setting Currency (pls see EDIT), but var currency still gets "" – BobSwanson Mar 10 '17 at 17:16
  • This might be useful reading: http://stackoverflow.com/questions/6484/how-do-you-mock-a-sealed-class – ProgrammingLlama Mar 10 '17 at 17:23

2 Answers2

2

This is how shadowing or hiding works i.e. (using new keyword with members of class), if you are expecting that holding derived class (CartFake) reference as base class (Cart) would give you access to the value of property of derived class (CartFake), you are wrong.

That would have happened if you had the property defined virtual in base class (Cart) and you had overriden it using override keyword in derived class (CartFake), but that is not the case.

For the behavior that you are expecting for that your code needs to be like:

public class Cart {
    public virtual string Currency { get; set; } // I'm trying to override this
}

// My fake class
public class CartFake : Cart
{
    public override string Currency {  // This should hide SomeBaseBase.Cart.Currency - but it does not
        get { return "USD"; }
        set { value = "USD"; }
    }
}

now when you access the property Currency using variable of type base class but object is actually of type Derived class, you will get USD back.

When you are accessing the Currency property using reference of type Cart it is hiding the property Currency defined in the CartFake.

You need to cast it back to CartFake, if you want to get USD as result of Currency like:

// class under test
public class SomeClassFake : Base {
    public override Cart cart => new CartFake();


    // Then when test is running I have this
    var cartFake = cart as CartFake;
    var currency = cartFake.Currency // will return USD 
}

Refer to the question Difference between Shadowing and Overriding for more clarity.

Community
  • 1
  • 1
Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
0

You need to cast Cart to the CartFake object who's property you want to return

var currency = ((CartFake)Cart).Currency;
BackDoorNoBaby
  • 1,445
  • 2
  • 13
  • 20