1

My primary reason for using an interface is to make unit testing easy. But I feel like I am not understanding how to use interfaces 100%.

Here's a simplified version of what I'm trying to do:

public interface IPlan { List<Plan> GetPlans(IPlan plan); List<Plan> GetAllPlans(); List<string> DoSomethingElse(); } public class Plan : IPlan { List<Plan> GetPlans(IPlan plan) { // List<Plan> planList = plan.GetAllPlans(); // // Do stuff with planList... // } 

For setting up a unit test I need to be able to mock the Plan class and return a set list of plans from GetAllPlans, so I see I should be using the interface here so that I can mock it properly. I also understand (or at least I think) that I should be passing in an IPlan object to GetPlans and then I should be using that IPlan object to call GetAllPlans... but something doesn't seem right with this set up.

Am I setting this up incorrectly? It seems weird that I am passing an IPlan that is the same type as the class that it is in (I'd be passing in an IPlan that is a Plan). Any advice on this?

2
  • 1
    Sorry I cannot quite follow you, 'I should be passing in an IPlan object to GetPlans', pass how? You are not passing anything. Can you explain what you want to achieve? Commented Nov 12, 2013 at 14:25
  • @RvdK: Sorry, I forgot to put in where I was passing the IPlan object, it has been edited. Commented Nov 12, 2013 at 14:37

4 Answers 4

2

Your confusion stems, I think, from the off nature of your Plan class. You have a class that presumably encapsulates some plan data, but that also provides methods to handle lists of itself.

Without seeing more code, it's hard to be sure, but you should probably start off by moving GetPlans and GetAllPlans into another class that handles lists of plans. Then it makes sense for their signatures to change to

List<IPlan> GetPlans(); List<IPlan> GetAllPlans(); 

of possibly even for the class to be generic, constrained on T : IPlan an thus the signatures being:

List<T> GetPlans(); List<T> GetAllPlans(); 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I think I see what you are saying. If I leave the Plan class as a definition of a Plan and add a class that does stuff with Plans I would move the GetPlans and GetAllPlans over there and things will probably start to make more sense. Or are you suggesting something else?
@kevinrcress That is indeed what I'm suggesting.
0

Well, technically your implementation is correct, but it seems odd for an interface to use a concrete implementation of that interface in its methods. it looks like IPlan is trying to "do too much".

I would instead have something like this:

public interface IPlanRepository { IEnumerable<IPlan> GetPlans(IPlan plan); IEnumerable<IPlan> GetAllPlans(); IEnumerable<string> DoSomethingElse(); } public class PlanRepository : IPlanRepository { IEnumerable<IPlan> GetPlans(IPlan plan) { // fill a List with Plans } IEnumerable<IPlan> planList = GetAllPlans(); { // fill a List with Plans } // // Do stuff with planList... // } public interface IPlan { // properties and methods relating to a Plan (NOT how to "get" a Plan) } public class Plan : IPlan { // implementation of properties and methods } 

Note that I also change the List return types to the more generic IEnumerable interface. This gives you flexibility in the implementation to return anything that returns an IEnumerable<Plan> such as List<Plan>, Plan[], or IQueryable<Plan> if you are using an ORM.

Comments

0

you are implementing it correctly. Every method defined in the interface must be implemented in your concrete class.

what I don't understand in your question is...

"It seems weird that I am passing an IPlan that is the same type as the class that it is in (I'd be passing in an IPlan that is a Plan). "

can you clarify?

if you mean the List GetPlans(), then things like this are totally fine and expected. you are planning to return a collection of plans.

the interface defines some skeleton methods that every class implementing should implement. this basis a "contract" to guarantee that the classes will have this interface implemented. this also means you can do things like plugins where you know you have an IPlugin interface and you can use say reflection to load assemblies which has this interface implemented and start calling methods in the classes.

perhaps you need an entity class called Plan and then rename your current Plan class which implements IPlan to PlanOperations or something. Seems that this class will be doing the work and your Plan is just an entity/object which may have get setters

Comments

0

An Interface is a contract, designed to be (potentially) applied to many objects. It basically tells your application that any object implementing the interface will implement the methods you are specifying in the interface.

It's designed for loose coupling. Instead of your method accepting a Plan object, e.g:

public bool DoSomething(Plan plan) { //.... } 

You can make it take IPlan:

public bool DoSomething(IPlan plan) { //.... } 

This means that at runtime, you could pass anything into that method, so long as it implements IPlan.

This also means that, for unit testing, you can create a dummy implementation of IPlan (for instance, if IPlan normally communicates with the DB, you would not want it to happen in your test) and pass it - so that you are only testing the code in the method, not that method and anything it calls inside Plan.

3 Comments

Thanks, your second example (DoSomething(IPlan plan)) is more specifically what I'm wondering about -- is it correct to pass in an IPlan object in a class that implements that interface?
As an extension to 'loose coupling', interfaces allow any class to participate in a _some other code's _system, regardless of the classes base type/namespace/assembly. You get the flexibility to add implementations to a class without re-designing everything. It allows you to 'fake' multiple inheritance...
@kevinrcress You can do. It depends on what you are intending to do I suppose. Your class is already aware of itself, so if it's returning a list of itself, then you wouldn't really need to pass an IPlan object in at all. It's more common to pass IPlan to methods not contained inside a class implementing it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.