2

Please can someone help me because I am getting confused.

I have an Entity like this:

public class Code
{
    public int ID { get; set; }
    public int UserID { get; set; }
    public string CodeText { get; set; }
}

and an Interface like this:

public interface ICodeRepository
{
    IQueryable<Code> Codes { get; }
    void AddCode(Code code);
    void RemoveCode(Code code);
    Code GetCodeById(int id);
}

and a Repository like this:

public class SQLCodeRepository : ICodeRepository
{
    private EFSQLContext context;

    public SQLCodeRepository()
    {
        context = new EFSQLContext();
    }

    public IQueryable<Code> Codes
    {
        get { return context.Codes; }
    }

    public void AddCode(Code code)
    {
        context.Codes.Add(code);
        context.SaveChanges();
    }

    public void RemoveCode(Code code)
    {
        context.Codes.Remove(code);
        context.SaveChanges();
    }

    public Code GetCodeById(int id)
    {
        return context.Codes.Where(x => x.ID == id).FirstOrDefault();
    }
}

and a Context like this:

public class EFSQLContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Code> Codes { get; set; }
    public DbSet<PortfolioUser> PortfolioUsers { get; set; }
}

If I declare my controller like this:

public class SearchController : Controller
{
    private ICodeRepository cRepo;

    public SearchController(ICodeRepository codeRepository)
    {
        cRepo = codeRepository;
    }
}

and then try to do cRepo.GetCodeById(1) nothing happens. But if I declare private ICodeRepository rep = new SQLCodeRepository and then call rep.GetCodeById(1) I can see the method in the Repository being called.

What am I doing wrong?

Maess
  • 4,118
  • 20
  • 29
markp3rry
  • 724
  • 10
  • 26
  • Added Ninject tag as OP says below he is using Ninject – Maess Nov 06 '12 at 14:40
  • Wnat does "and then try to do cRepo.GetCodeById(1) nothing happens" mean? – Steven Nov 07 '12 at 09:56
  • It means I need to do some more reading and research. The Microsoft ASP.NET team write "The mock repository implements the methods of the IContactManagerRepository interface, but the methods don t actually do anything." [link]http://www.asp.net/mvc/tutorials/older-versions/contact-manager/iteration-5-create-unit-tests-cs – markp3rry Nov 07 '12 at 10:36
  • Correct, the purpose of a mock is to pretend a method call happened and exhibited some expected behavior, so that in a unit test, for example, you are only testing the behavior of the System Under Test, not everything else downstream. I suggest using the "Verify" method with Moq to verify with your test that the GetCodeById(1) method is called, and then writing separate tests on the GetCodeById method. – Facio Ratio Nov 14 '12 at 16:36

1 Answers1

3

It looks like from the constructor signature, you are going to be doing some dependency injection. The step you are missing is to set up a DI container using a tool like Castle Windsor. You then configure the MVC resolver to use the DI container to give you the correct implementation of ICodeRepository.

See this

You'll need to create a resolver that implements IDependencyResolver and IDependencyScope and a controller factory that inheritsDefaultControllerFactory

Once you have those you can do something like the following:

MyContainer container; // this needs to be a class level member of the asax
var configuration = GlobalConfiguration.Configuration;

container = new MyContainer() // may need additional stuff here depending on DI tool used

configuration.DependencyResolver = new MyDependancyResolver(container);
var mvcControllerFactory = new MyFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(mvcControllerFactory);

You would call the above code from the asax Application_Start()

See this answer for more specifics on using Ninject and MVC3

Community
  • 1
  • 1
Maess
  • 4,118
  • 20
  • 29
  • Not a ninject expert, sorry, but maybe someone else can jump in? I think what you are missing is adding your container to the resolver. (OP had posted comment that he was using ninject). – Maess Nov 06 '12 at 14:24
  • OK... I am using Ninject for DI. I have this in the NinjectControllerFactory class: `Mock mockCode = new Mock(); mockCode.Setup(m => m.Codes).Returns(new List { new Code{ID = 1, UserID = 1, CodeText = "A700"} }.AsQueryable()); ninjectKernel.Bind().ToConstant(mockCode.Object);` Can you explain a bit more about using the MVC resolver? – markp3rry Nov 06 '12 at 14:24
  • See my edits for a general, non-ninject specific example of how you could go about this. – Maess Nov 06 '12 at 14:33
  • If I inject a Moq Interface (am I using the right terminology) via the NinjectControllerFactory then the method call to GetCodeById doesn't work. But if I inject the SQlCodeRepository then the method call does work. Why wouldn't the method call work on the Mocked interface? This is also messing with my unit testing - I'm following a guide showing me how to write tests with Moq but then when I come to test the Controller the test fails because the GetCodeById method call doesn't work. – markp3rry Nov 06 '12 at 14:39
  • I would guess some sort of issue with your Moq. Is your container properly resolving the Moq as ICodeRepository? What happens if you take DI out of the equation and just do cRepo = new mockCode? – Maess Nov 06 '12 at 14:41
  • I posted the Moq code in the NinjectControllerFactory above. Can anyone see if I have made a mistake in the Setup? – markp3rry Nov 06 '12 at 14:44