Search code examples
.netasp.net-mvcunit-testingmocking

Mock Controller constructor parameters with fakeeasy in dotnet


I am try to write a unit test for the controller in .net. Actually I am new to .net framework. When I try to mock the controller with Fakeeasy I reserved a error message. Some one can help me to solve this issue.

This is the test class.

public class TagControllerTest
{
    private TagController _tagController;
    private ApplicationDbContext _applicationDbContextMock;

    public TagControllerTest()
    {
        _applicationDbContextMock = A.Fake<ApplicationDbContext>();

        _tagController = new TagController(_applicationDbContextMock);

    }

    [Fact]
    public void TagController_Add_ReturnSuccess()
    {
        var response = _tagController.Add();

        response.Should().BeOfType<IActionResult>();
    }

}

this is the error message I reserved.

FakeItEasy.Core.FakeCreationException : 
  Failed to create fake of type blog_dotnet_mvc.DataAccess.ApplicationDbContext:

  Below is a list of reasons for failure per attempted constructor:
    Constructor with signature (Microsoft.EntityFrameworkCore.DbContextOptions`1[blog_dotnet_mvc.DataAccess.ApplicationDbContext]) failed:
      No constructor matches the passed arguments for constructor.
      An exception of type System.InvalidOperationException was caught during this call. Its message was:
      The DbContextOptions passed to the ApplicationDbContextProxy constructor must be a DbContextOptions<ApplicationDbContextProxy>. When registering multiple DbContext types, make sure that the constructor for each context type has a DbContextOptions<TContext> parameter rather than a non-generic DbContextOptions parameter.
         at Microsoft.EntityFrameworkCore.DbContext..ctor(DbContextOptions options)
         at blog_dotnet_mvc.DataAccess.ApplicationDbContext..ctor(DbContextOptions`1 options) in E:\localrepo\blog-dotnet-mvc\blog-dotnet-mvc\DataAccess\ApplicationDbContext.cs:line 8
         at Castle.Proxies.ApplicationDbContextProxy..ctor(IInterceptor[], DbContextOptions`1 options)
         at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
         at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)


  Stack Trace: 
FailedCreationResult.get_Result() line 82
FakeAndDummyManager.CreateFake(Type typeOfFake, Action`1 optionsBuilder, LoopDetectingResolutionContext resolutionContext) line 42
FakeAndDummyManager.CreateFake(Type typeOfFake, LoopDetectingResolutionContext resolutionContext) line 28
A.Fake[T]() line 31
TagControllerTest.ctor() line 24
RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)

this is the controller

namespace blog_dotnet_mvc.Controllers
{
    public class TagController : Controller
    {

        private readonly ApplicationDbContext _dbContext;

        public TagController(ApplicationDbContext dbContext)
        {
            _dbContext = dbContext;
        }


        [HttpGet]
        public IActionResult Add()
        {
            return View();
        }
    }
}

this is the ApplicationDbContext class

using blog_dotnet_mvc.Models.Domain;
using Microsoft.EntityFrameworkCore;

namespace blog_dotnet_mvc.DataAccess
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
        }

        public DbSet<BlogPost> BlogPosts { get; set; }
        public DbSet<Tag> Tags { get; set; }
    }
}

Can someone help me to solve this. Thank you very much.

Edit

as said this worked

 _applicationDbContextMock = A.Fake<ApplicationDbContext>(x => x.WithArgumentsForConstructor(() => new ApplicationDbContext(new DbContextOptions<ApplicationDbContext>())));

Solution

  • The ApplicationDbContext class does not have a parameter-less constructor, either provide one, or include the constructor parameters when creating the fake as demonstrated here.

    var foo = A.Fake<FooClass>(x => x.WithArgumentsForConstructor(() => new FooClass("foo", "bar")));