Avais
Avais

Reputation: 119

new keyword not forcing hiding - OOP C#

I have the following scenario:

I want to mock an interface so I can unit test my app. I am trying not to create a new mock class implementing my interface but creating a new class that inherits the original concrete class and use new keyword to force new behaviour when that method would be called. But for some reason, the concrete classs' method is being called and not the class that I created (as a mock)

Following Code:

public interface IMyService 
{ 
    Model GetModelData(int id)
}

public class MyService : IMyService
{
    public Model GetModelData(int id)
    { 
       //call to db     
    }
}

public class MyService2 : MyService
{
    public MyService2()
        : base(new MyRepository())
    {    
    }

    public new Model GetModelData(int id)
    { 
        return new Model();
    }
}

Injecting dependency:

x.ForRequestedType<IMyService>().TheDefaultIsConcreteType<MyService2>();

Retrieving the concrete class : on debugging I can see myService points to MyService2 class but the method executes on MyService class.

_myServie = ObjectFactory.GetInstance<IMyService>();
                Model modelData = _myServie.GetModelData(5);

Upvotes: 4

Views: 425

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1501586

Just using new creates a new method without associating it with the interface. You're using the interface in your real code (I assume) so you want the binding of the interface method to the new method. To do that, you have to declare that you're implementing the interface again. Here's an example showing the difference:

using System;

interface IFoo
{
    void Bar();
}

class Normal : IFoo
{
    public void Bar()
    {
        Console.WriteLine("Normal.Bar");
    }
}

class Extended1 : Normal
{
    public new void Bar()
    {
        Console.WriteLine("Extended1.Bar");
    }
}

class Extended2 : Normal, IFoo
{
    public new void Bar()
    {
        Console.WriteLine("Extended2.Bar");
    }
}

class Test
{
    static void Main()
    {
        IFoo x = new Extended1();
        IFoo y = new Extended2();

        x.Bar();
        y.Bar();
    }
}

Output:

Normal.Bar
Extended2.Bar

So if you change your class declaration to:

public class MyService2 : MyService, IMyService

you should find it just works. I can't say I'm a big fan of this approach, mind you - anything within MyService which calls the method will call its own implementation unless it happens to call through an IMyService-type reference. You could make the interface implementation in your concrete class virtual and override it in your subclass instead; that would be better in someways but worse in others. Basically, this sort of "half-inheritance" feels pretty fragile to me.

I suspect it would be cleaner if you had an abstract base class that both your real implementation and your test implementation derived from...

Upvotes: 6

David Watts
David Watts

Reputation: 2289

I think what you are looking for is making the method on MyService virtual and overriding it in MyService2. Like so:

public interface IMyService 
{ 
    Model GetModelData(int id)
}

public class MyService : IMyService
{
    public virtual Model GetModelData(int id)
    { 
       //call to db     
    }
}

public class MyService2 : MyService
{
    public MyService2()
        : base(new MyRepository())
    {    
    }

    public override Model GetModelData(int id)
    { 
        return new Model();
    }
}

This way, if the method is overridden in the child class, then the child classes method will be called, otherwise the base class will consume the method call.

Upvotes: 1

Related Questions