how to unit test controller that in turn calls repository with two parameters - asp.net-mvc-4

At present, I am writing unit tests for my controller. Below is the structure of my code in the project.
MyController Class
public class MyController : Controller
{
private readonly MyRepository _myRepository;
public MyController()
: this(new MyRepository())
{
}
[HttpGet]
public ActionResult Index()
{
var items = _myRepository.GetAllItems();
if (items.Count() == 0)
return View("EmptyItems");
else
{
return View("List", items);
}
}
}
MyRepository Class
public class MyRepository : IDisposable, IMyRepository
{
private readonly MyDbContext _dbcontext;
private readonly ISecurityService _securityService;
public TodoListItemsRepository() : this(new MyDbContext(), new SecurityService())
{
}
public TodoListItemsRepository(MyDbContext context, ISecurityService securityService)
{
_dbcontext = context;
_securityService = securityService;
}
public IEnumerable<MyModel> GetAllItems()
{
var userid = _securityService.GetUser();
var todoList = _dbcontext.MyList.Where(e => e.UserId == userid);
return todoList;
}
//Other Methods etc...
......
}
SecurityService class
public class SecurityService : ISecurityService
{
public int GetUser()
{
return (int)Membership.GetUser().ProviderUserKey;
}
}
Here all methods inside my repository depends on GetUser method. Hence, I have initialized it inside the constructor. The repository class is initialized from the controller constructor.
My issue is - I couldn't unit the Index action unless I need to initialize dbcontext and the securityservice. Could someone please advise me if I am doing the right thing or any changes required in the structure of my code so that I can unit test my application ? I am new to MVC. So, any suggestions would be much appreciated.

Related

EF Core how to get a DBContext in a class instance?

The ASP NET Core project uses the Entity Framework Core.
From the method of the Home controller I call Task.Run for the method of the instance of the class MyClass, where I need to access the data from the database.
I tried to pass _dbContext to the constructor of the MyClass class, but I get the exception
Cannot access a disposed object.
HomeController
[Route("api/[controller]")]
[EnableCors("AllowAllOrigin")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly DataBaseContext _dbContext;
public HomeController (DataBaseContext dbContext)
{
_dbContext = dbContext;
}
[EnableCors("AllowAllOrigin")]
[HttpPost("[action]")]
public string UpdateBotSettings()
{
MyClass myClass = new MyClass(_dbContext);
Task task = Task.Run(() => myClass.AnyMethod());
}
}
MyClass
public class MyClass
{
private readonly DataBaseContext _dbContext;
public MyClass(DataBaseContext dbContext)
{
_dbContext = dbContext;
}
public async void AnyMethodAsync()
{
MyData myData = _dbContext.AnyData.Where(d => d.id == 1).FirstOrDefault(); // <- exception
}
}
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
string connection = Configuration.GetConnectionString("ConnectionDB");
services.AddDbContext<DataBaseContext>(options => options.UseSqlServer(connection));
// another code
}
Can you please tell me how to access dbContext inside an instance of MyClass?
Most important mistake in your code is that you are using async void in your AnyMethodAsync() method of the Myclass. Don't use async void in your code, instead use async Task. Here is the details: C# – beware of async void in your code
So write your AnyMethodAsync() as follows:
public async Task AnyMethodAsync()
{
MyData myData = await _dbContext.AnyData.Where(d => d.id == 1).FirstOrDefault();
}
Now you can register your MyClass to the ASP.NET Core DI container as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<MyClass>(); // <-- here it is
string connection = Configuration.GetConnectionString("ConnectionDB");
services.AddDbContext<DataBaseContext>(options => options.UseSqlServer(connection));
// another code
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Now use it as follows:
[Route("api/[controller]")]
[EnableCors("AllowAllOrigin")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly DataBaseContext _dbContext;
private readonly MyClass _myClass
public HomeController (DataBaseContext dbContext, MyClass myClass)
{
_dbContext = dbContext;
_myClass = myClass;
}
[EnableCors("AllowAllOrigin")]
[HttpPost("[action]")]
public async Task<string> UpdateBotSettings()
{
await _myClass.AnyMethod();
// rest of codes
}
}

Not Able to call the service layer in controller in mvc

Exception:
Nullreference exception
Here is my Code:
Controller:
private IUserService UserService;
public HomeController()
{
}
public HomeController(IUserService UserService)
{
this.UserService = UserService;
}
[HttpPost]
public ActionResult Register(RegisterViewModel reg)
{
SADM_Users users = new SADM_Users();
if (reg == null)
{
return Json(false);
}
else
{
FillUserMaster(users, reg);
UserService.insertUser(users);
ViewBag.ErrorMsg = "Succesfully added";
}
return View();
}
Service Layer:
public interface IUserService
{
void insertUser(SADM_Users users);
}
public class UserService:IUserService
{
private readonly ILoginRepository LoginRepository;
private readonly IUnitOfWork unitOfWork;
public UserService(ILoginRepository LoginRepository)
{
this.LoginRepository = LoginRepository;
}
public void insertUser(SADM_Users users)
{
try
{
LoginRepository.Add(users);
unitOfWork.Commit();
}
finally {
users = null;
}
}
}
I'm creating an mvc app with a service layer. I'm used to call services using in my controllers, but these services have not been Called.
please some one help on this.and i wnt to know any dependancy factor.
Remove the default constructor from your HomeController and make sure that you are using a DI library that will inject the proper implementation of IUserService into it.

What is the best way to wrap dbContext for DI?

I am thinking something like the following may work ok for injecting dbcontext via constructor to my service layer.... Does anyone out there have a better way?
It seems to work however _context.EntityName etc don't show up in intellisense unless I cast the object to the actual class that inherits from dbcontext.
public interface IContextFactory:IDisposable
{
DbContext Create();
}
public class ContextFactory<TContext> : IContextFactory where TContext : DbContext, new()
{
private DbContext _context;
public DbContext Create()
{
_context = new TContext();
_context.Configuration.LazyLoadingEnabled = true;
return _context;
}
public void Dispose()
{
_context.Dispose();
}
}
As Steven mentioned in his comment, you can just inject the DbContext directly from your Composition Root. Here is an example of how this could work with SimpleInjector.
container.Register<MyDbContext>(
() => new MyDbContext("name=MyDbContext"),
new WebRequestLifestyle(true));
Where MyDbContext is a subclass of DbContext:
public class MyDbContext: DbContext
{
public MyDbContext(string connectionString)
: base(connectionString)
{
this.Configuration.LazyLoadingEnabled = true;
}
/* DbSets<SomeEntity> etc */
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//etc
}
}

How to implement EF Code First and WCFDataService

A bit of history first. I created a EF Code First Library that contains POCO Objects as my Models, a generic DataProvider that inherits from DbContext, generic Repostory that implements the generic DataProvider, and a generic Service that implements the repository. I have used this library successfully in WPF (MVVM), ASP.Net, Window Forms, and ASP MVC applications.
For this discussion I will reference the Company Model
From the top down, I create a Service class called CompanyService that inherits from a base Service Class. The CompanyService class contains all of the business logic for the Company Model. This class uses the Repository class to perform the CRUD operations. The Repository then encapsulates all the DataProvider class operations.
I have done some research on using EF with WCFDataService, but I can't get my head around how to implement my library with it, particulary when it comes to overriding the CreateDataSource() Method.
It may be that I should just use a WCF Service instead, maybe I'm not understanding the purpose of the WCFDataService.
I have listed partial code for the classes involved:
public class CompanyService : ServiceBase<Company> ,ICompanyService
{
public Company GetCompanyByFolderId(string eFolderId)
{
return (Company)GetModelByFolderId(eFolderId);
}
}
public abstract class ServiceBase<TModel> : IService<TModel> where TModel : class, IModel
{
private IDataProvider _dataProvider;
public IDataProvider DataProvider
{
get
{
if (_dataProvider == null)
{
string connectionStringName = Properties.Settings.Default.DataProvider;
bool enableLazyLoading = true;
_dataProvider = new DataProvider(connectionStringName, enableLazyLoading);
}
return _dataProvider;
}
set
{
_dataProvider = value;
}
}
private IRepository<TModel> _repository;
public IRepository<TModel> Repository
{
get
{
if (_repository == null)
{
_repository = new Repository<TModel>(DataProvider);
}
return _repository;
}
set
{
_repository = value;
}
}
public TModel GetModelByFolderId(String folderId)
{
return GetTable().FirstOrDefault(o => o.EFolderid == folderId);
}
public virtual IQueryable<TModel> GetTable()
{
return Repository.GetTable();
}
}
public class Repository<TModel> : IRepository<TModel> where TModel : class, IModel
{
private IDataProvider _dataProvider;
public Repository(IDataProvider dataProvider)
{
_dataProvider = dataProvider;
}
private IDbSet<TModel> DbSet
{
get
{
return _dataProvider.Set<TModel>();
}
}
public IQueryable<TModel> GetTable()
{
return _dataProvider.GetTable<TModel>();
}
}
public class DataProvider : DbContext, IDataProvider
{
public DataProvider()
{
}
public DataProvider(string connectionStringName, bool enableLazyLoading = true)
: base(connectionStringName)
{
Configuration.LazyLoadingEnabled = enableLazyLoading;
//Configuration.ProxyCreationEnabled = false;
}
public new IDbSet<TModel> Set<TModel>() where TModel : class
{
return base.Set<TModel>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CompanyMapping());
base.OnModelCreating(modelBuilder);
}
public IQueryable<TModel> GetTable<TModel>() where TModel : class
{
return Set<TModel>().AsQueryable();
}
}
Then my Test looks something like this:
[TestClass()]
public class CompanyServiceTest
{
[TestMethod()]
public void GetCompanies()
{
CompanyService target = new CompanyService();
IQueryable<Company> companies = target.GetTable();
Assert.IsNotNull(companies);
}
[TestMethod()]
public void GetCompanyByFolderId()
{
CompanyService target = new CompanyService();
Company company = target.GetCompanyByFolderId("0000000000000000000000000172403");
Assert.IsNotNull(company);
}
}

Unit Of Work & Generic Repository with Entity Framework 5

I'm using ASP.NET MVC 4 with Entity Framework 5. I have model classes and Entity Maps to map existing tables to those model classes. All this is setup fine and works great.
Now I want to mock this. I created Unit Of Work that takes the DataContext and uses a Generic Repository. Upon that I built services to be able to get data from many repositories at once and only needing to have one instance of the DataContext. This also works great.
Now to the problem: I want to test the services, with mock data. When I create the Unit Of Work instance, I want to be able to insert a DataContext that is mocked instead of the real DataContext.
I tried to create a IContext interface and let the real and mocked DataContext implement that but ran into problems with DbSet. I tried to use IDbSet and creating a FakeDbSet but without success. I also read on the internet that mocking the context with IDbSet and using a FakeDbSet is a bad approach.
Do you have any idea what would be the best way to achieve this? What I have now is the behavior I would like to keep, but would really like to be able to mock the data from the Model classes in the DataContext.
I'm aware of that Entity Framework already comes with Unit Of Work behavior and that you don't need to add extra behavior on top of that. But I wanted to wrap that inside of another class that keeps track of all the repositories (called UnitOfWork class).
Edit: I wrote two articles explaining my solution with both LINQ and Entity Framework.
http://gaui.is/how-to-mock-the-datacontext-linq/
http://gaui.is/how-to-mock-the-datacontext-entity-framework/
Here's my code:
IRepository.cs
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
T GetById(long Id);
IEnumerable<T> All();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}
IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
Repository.cs
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbset;
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
var entry = _context.Entry(entity);
entry.State = System.Data.EntityState.Deleted;
}
public virtual void Update(T entity)
{
var entry = _context.Entry(entity);
_dbset.Attach(entity);
entry.State = System.Data.EntityState.Modified;
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> All()
{
return _dbset;
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dbset.Where(predicate);
}
}
UnitOfWork.cs
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private Dictionary<Type, object> _repositories;
private bool _disposed;
public UnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
_disposed = false;
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
if (_repositories.Keys.Contains(typeof(TEntity)))
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
var repository = new Repository<TEntity>(_ctx);
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void Save()
{
_ctx.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
_ctx.Dispose();
}
this._disposed = true;
}
}
}
ExampleService.cs
public class ExampleService
{
private IRepository<Example> m_repo;
public ExampleService(IUnitOfWork uow)
{
m_repo = uow.GetRepository<Example>();
}
public void Add(Example Example)
{
m_repo.Add(Example);
}
public IEnumerable<Example> getAll()
{
return m_repo.All();
}
}
ExampleController.cs
public IEnumerable<Example> GetAll()
{
// Create Unit Of Work object
IUnitOfWork uow = new UnitOfWork<AppDataContext>();
// Create Service with Unit Of Work attached to the DataContext
ExampleService service = new ExampleService(uow);
return service.getAll();
}
Your ExampleService class is expecting IUnitOfWork, that means you just need another IUnitOfWork that is a Mock and its GetRepository() method will return an IRepository Mock.
For example (not really a Mock but In-Memory stub):
public InMemoryRepository<T> : IRepository<T> where T : class
{
........
}
public InMemoryUnitOfWork : IUnitOfWork
{
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
return new InMemoryRepository<TEntity>();
}
}
Then:
public IEnumerable<Example> GetAll()
{
// Create Unit Of Work object
IUnitOfWork uow = new InMemoryUnitOfWork();
// Create Service with Unit Of Work
ExampleService service = new ExampleService(uow);
return service.getAll();
}
You can follow the following link it is very helpful.
Generic Repository Pattern in MVC3 Application with Entity Framework
Entity Framework and Data Patterns