Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TDD Unit of Work Pattern Moq Cannot instantiate proxy of class error

I am new to test driven development, and trying to unit test an mvc application. I am using Moq and Ninject, and trying to follow the unit of work repository pattern. I am getting a System.ArgumentException Error for all of my tests. Here is the error message and error stack trace:

Test method LOMSv4.Tests.Controllers.AutobytelControllerTest.Index_Contains_All_Requests threw exception: 
System.ArgumentException: Can not instantiate proxy of class: LOMSv4_DAL.Autobytel.Concrete.RequestRepository.
Could not find a parameterless constructor.

Parameter name: constructorArguments

Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
Moq.Proxy.CastleProxyFactory.CreateProxy[T](ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
Moq.Mock`1.<InitializeInstance>b__0()
Moq.PexProtector.Invoke(Action action)
Moq.Mock`1.InitializeInstance()
Moq.Mock`1.OnGetObject()
Moq.Mock.GetObject()
Moq.Mock.get_Object()
Moq.MockDefaultValueProvider.ProvideDefault(MethodInfo member)
Moq.QueryableMockExtensions.FluentMock[T,TResult](Mock`1 mock, Expression`1 setup)
lambda_method(Closure )
Moq.Mock.GetInterceptor(Expression fluentExpression, Mock mock)
Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
Moq.PexProtector.Invoke[T](Func`1 function)
Moq.Mock.Setup[T,TResult](Mock mock, Expression`1 expression, Func`1 condition)
Moq.Mock`1.Setup[TResult](Expression`1 expression)

Here is my test class:

[TestClass]
public class AutobytelControllerTest
{
    Mock<IUnitOfWork> mock = new Mock<IUnitOfWork>();

    [TestMethod]
    public void Index_Contains_All_Requests()
    {
        //Arrange
        AutobytelController controller = new AutobytelController(mock.Object);
        mock.Setup(m => m.RequestRepository.SelectAll()).Returns(new abtRequest[] {
            new abtRequest {RequestID = 1, Title = "Request 1", Description = "Request Description1", UserName = "NewUser", RequestStatus = 0},
            new abtRequest {RequestID = 2, Title = "Request 2", Description = "Request Description2", UserName = "ReturnUser", RequestStatus = 1}
        }.AsQueryable());

        //Act
        abtRequest[] result = ((AutobytelHomeViewModel)controller.Index().Model).Requests.ToArray();
        //Assert
        Assert.AreEqual(result.Length, 2);
        Assert.AreEqual("Request 1", result[0].Title);
        Assert.AreEqual("Request 2", result[1].Title);
    }

I have an IUnitofWork interface and class, generic repository interface and class and a request repository that implements the generic repository

public interface IUnitOfWork
{
    RequestRepository RequestRepository { get; }
    void Save();
}

public class UnitOfWorkRepository : IUnitOfWork, IDisposable
{
    private AutobytelEntities context = new AutobytelEntities();
    private RequestRepository requestRepository;

    public RequestRepository RequestRepository
    {
        get
        {
            if (this.requestRepository == null)
            {
                //this.requestRepository = new GenericRepository<abtRequest>(context);
                this.requestRepository = new RequestRepository(context);
            }
            return requestRepository;
        }
    }

    public void Save()
    {
        context.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    internal AutobytelEntities context;
    internal IObjectSet<TEntity> objectSet;


    public GenericRepository(AutobytelEntities context)
    {
        this.context = context;
        this.objectSet = context.CreateObjectSet<TEntity>();
    }

    public virtual IQueryable<TEntity> SelectAll()
    {
        return objectSet.AsQueryable();
    }

    public virtual TEntity Update(TEntity entity)
    {
        context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
        return entity;
    }

    public virtual void Delete(TEntity entity)
    {
        objectSet.DeleteObject(entity);
    }
}

    public class RequestRepository : GenericRepository<abtRequest>, IGenericRepository<abtRequest>
{
    public RequestRepository(AutobytelEntities context) : base(context)
    { }

    public virtual abtRequest SelectByUserName(string username)
    {
        return context.abtRequests.FirstOrDefault(i => i.UserName == username && (i.RequestStatus == 0 || i.RequestStatus == 1));
    }

    public virtual abtRequest SelectByRequestID(int requestID)
    {
        return context.abtRequests.FirstOrDefault(i => i.RequestID == requestID);
    }

Using Ninject I am binding my IUnitofwork to UnitOfWork class.

If I add a parameterless constructor to my request repository, My error is resolved- but because I don't want to create a new object context, I want to pass my context in from the unit of work repository.

How can I resolve this error?

like image 954
Jillian Avatar asked Feb 20 '23 10:02

Jillian


2 Answers

I resolved this error by adding an Interface to my RequestRepository and creating an instance of that interface in my unit of work. My IUnit of Work changed to:

public interface IUnitOfWork
{
    IRequestRepository RequestRepository { get; }
    void Save();
}

Inside my UnitOfWork Repository changed to:

private IRequestRepository requestRepository;

public IRequestRepository RequestRepository
{
    get
    {
        if (this.requestRepository == null)
        {
            this.requestRepository = new RequestRepository(context);
        }
        return requestRepository;
    }
}
like image 66
Jillian Avatar answered Apr 28 '23 19:04

Jillian


This is just pseudo-code but I hope it gets you closer to a solution. You should be able to set up your mocks along these lines:

//Arrange
var mockRepository = new Mock<RequestRepository>("CONSTRUCTOR ARGUMENT");
mockRepository.Setup(mr => mr.SelectAll()).Returns(new abtRequest[] {
            new abtRequest {RequestID = 1, Title = "Request 1", Description = "Request Description1", UserName = "NewUser", RequestStatus = 0},
            new abtRequest {RequestID = 2, Title = "Request 2", Description = "Request Description2", UserName = "ReturnUser", RequestStatus = 1}
            }.AsQueryable());
mock.SetupGet(uow => uow.RequestRepository).Returns(mockRepository.Object);

AutobytelController controller = new AutobytelController(mock.Object);

The code above has a placeholder for your constructor argument ("CONSTRUCTOR ARGUMENT") - just supply the simplest thing here that will work for your test scenario.

like image 21
Ian Gilroy Avatar answered Apr 28 '23 19:04

Ian Gilroy