I have a service layer in my application which contains services such as AccountService, UserService and DocumentService.
I use StructureMap for my dependency injection so the constructor of my service might look like this:
public AccountService(IAccountRepository repo)
{
this.accountRepository = repo;
}
Now if I need access to say the UserService whilst in there is it good form to have the following?
public AccountService(IAccountRepository repo, IUserService user)
{
this.accountRepository = repo;
this.userService = user;
}
Yes, it perfectly fine. You can download the code and watch the episodes Rob Conery prepared.
public class CatalogService : Commerce.Services.ICatalogService
{
ICatalogRepository _repository = null;
IOrderService _orderService = null;
/// <summary>
/// Creates a CatalogService based on the passed-in repository.
/// </summary>
/// <param name="repository">An ICatalogRepository</param>
public CatalogService(
ICatalogRepository repository, IOrderService orderService)
{
_repository = repository;
_orderService = orderService;
if (_repository == null)
throw new InvalidOperationException("Repository cannot be null");
}
...
}
He injects the OrderService in the CatalogService.
Related
Does anyone know how we can inject context into User Manager > MongoDB serStore at runtime in .net core 2.0.
We cannot do this at startup due to the context being dynamic but the UserStore is not accessible and UserManager has too many variables to new up, and it is wrong. Are there any solutions?
public class UserStore<TUser> :
IUserPasswordStore<TUser>,
IUserRoleStore<TUser>,
IUserLoginStore<TUser>,
IUserSecurityStampStore<TUser>,
IUserEmailStore<TUser>,
IUserClaimStore<TUser>,
IUserPhoneNumberStore<TUser>,
IUserTwoFactorStore<TUser>,
IUserLockoutStore<TUser>,
IQueryableUserStore<TUser>,
IUserAuthenticationTokenStore<TUser>
where TUser : IdentityUser
{
private readonly IMongoCollection<TUser> _Users;
//THIS IS WHERE WE WANT TO INJECT THE users AT RUNTIME
public UserStore(IMongoCollection<TUser> users)
{
_Users = users;
}
public virtual void Dispose()
{
// no need to dispose of anything, mongodb handles connection pooling automatically
}
public virtual async Task<IdentityResult> CreateAsync(TUser user, CancellationToken token)
{
await _Users.InsertOneAsync(user, cancellationToken: token);
return IdentityResult.Success;
}
unfortunately users is null at startup, and should be as the tenant has not been created at that point.
We have also been using the saaskit.Multitenancy and just can't find a solution.
Any help would be much appreciated.
Thanks
i think u need a generic repository to act as a wrapper for IMongoCollection then inject the repository inside controllers
public class Repository<T>
{
public IMongoCollection<T> Collection { get; private set; }
public Repository(IDbFactory dbFactory)
{
MongoClient client = new MongoClient("ur connection string");
this.Collection = client.GetDatabase("db").GetCollection<T>(typeof(T).Name);
}
public T Find(Expression<Func<T, bool>> filter)
{
return this.Collection.AsQueryable<T>().FirstOrDefault<T>(filter);
}
public async Task<T> FindAsync(Expression<Func<T, bool>> filter)
{
return await this.Collection.AsQueryable<T>().FirstOrDefaultAsync<T>(filter);
}
// here add more methods
}
then register the dependency as below inside Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
services.AddMvc();
}
finally inside controllers u inject the generic repository, also dont forget to Implement the IDisopsible in genereic repository
public class ProductController : Controller
{
private readonly IRepository<Product> _productRepository = null;
public ProductController(IRepository<Product> productRepository)
{
this._productRepository = productRepository;
}
}
I have an MVC app (EF6, SQL Server CE 4), that I recently refactored to add a UnitOfWork class and a service layer (so that I could utilise a single DbContext per request, and conduct transactions successfully).
Previously, I was using Unity to inject the repositories into the controller. My unit tests (for the controllers) were simple to setup - I just mocked each repository, and passed those into the controller constructor.
After refactoring, I now use Unity to inject the Service Layer (to the controller) and UnitOfWork (into the Service Layer). The Service Layer now instantiates each repository, by passing the UnitOfWork.DbContext to the repository's constructor.
In my Unit Tests, I am attempting to mock the UnitOfWork, and the ServiceLayer (and pass the mocked UnitOfWork object into the ServiceLayer's constructor). However, the tests fail, saying "TestFixtureSetup failed in ControllerTest".
I assume it's due to how I'm attempting to pass the UnitOfWork mock into the ServiceLayer mock, so would appreciate any guidance on how to do this correctly.
Relevant code snippets below.
UnitOfWork
public interface IUnitOfWork:IDisposable
{
void Save();
IDSMContext Context { get; }
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private IDSMContext _context;
public UnitOfWork()
{
_context = new IDSMContext();
}
public IDSMContext Context
{
get {return _context;}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Service Layer
public interface IService
{
// Repositories
IUserRepository Users { get; }
IUserTeamRepository UserTeams { get; }
IPlayerRepository Players { get; }
IGameRepository Games { get; }
IUserTeam_PlayerRepository UserTeamPlayers { get; }
void Save();
}
public class Service: IService, IDisposable
{
private IUnitOfWork _unitOfWork;
private IUserRepository _userRepository;
private IUserTeamRepository _userTeamRepository;
private IPlayerRepository _playerRepository;
private IGameRepository _gameRepository;
private IUserTeam_PlayerRepository _userTeamPlayerRepository;
public Service(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
initialiseRepos();
}
private void initialiseRepos(){
_userRepository = _userRepository ?? new UserRepository(_unitOfWork.Context);
_userTeamRepository = _userTeamRepository ?? new UserTeamRepository(_unitOfWork.Context);
_playerRepository = _playerRepository ?? new PlayerRepository(_unitOfWork.Context);
_gameRepository = _gameRepository ?? new GameRepository(_unitOfWork.Context);
_userTeamPlayerRepository = _userTeamPlayerRepository ?? new UserTeam_PlayerRepository(_unitOfWork.Context);
}
public IUserRepository Users { get { return _userRepository; } }
public IUserTeamRepository UserTeams { get { return _userTeamRepository; } }
public IPlayerRepository Players { get { return _playerRepository; } }
public IGameRepository Games { get { return _gameRepository; } }
public IUserTeam_PlayerRepository UserTeamPlayers { get { return _userTeamPlayerRepository; } }
public void Save()
{
_unitOfWork.Save();
}
Unity Container Instance Setup
Instance.RegisterType<IService, Service>(new PerThreadLifetimeManager())
.RegisterType<IUnitOfWork, UnitOfWork>();
Controller Constructor
public GameController(IService service)
{
_service = service;
}
Test Constructor
_mockUnitOfWork = new Mock<IUnitOfWork>();
_mockServiceLayer = new Mock<IService>(_mockUnitOfWork.Object); //this line fails
Test Controller Method
GameController Controller = new GameController(_mockServiceLayer.Object);
If you want to test methods of GameController you just need to mock/stub the dependencies of that class. Just do this:
_mockServiceLayer = new Mock<IService>();
_controller = new GameController(_mockServiceLayer.Object);
When you are testing the Controller, you shouldn't worry about the dependencies of the service. UnitOfWork is never exposed outside your service, so don't worry about it when testing the controller. On your tests you may now setup expectations of methods called on your service, like verifying that Save was called once (If you were testing the service, then you would worry about the IService.Save calling Save on a mock of the IUnitOfWork!):
_mockServiceLayer.Verify(s=> s.Save(), Times.Once());
The problem you will find is that your service class is not abstracting the controller from the repositories, as your controller will get the repositories via the properties in IService and query directly the repositories. So if you want to test your controller methods, you will still need to mock the repositories, doing something like:
//Initialization before each test:
_mockUserRepo = new Mock<IUserRepository>();
//...other repositories
_mockServiceLayer = new Mock<IService>();
_mockServiceLayer.Setup(s => s.Users).Returns(_mockUserRepo.Object);
//... setup properties in IService for other repositories
_controller = new GameController(_mockServiceLayer.Object);
//In some test:
var user = new User();
_mockUserRepo.Setup(s => s.Get(123)).Returns(user);
call some controller method and make sure returned model is "user"
This way you may find yourself configuring the expectations and data returned by a few repositories and the UnityOfWork, just for testing the methods in the Controller! Not to mention that your Controller class effectively depends on your repositories, not just on the service.
Another approach would be if your service class contains higher level methods like GetUser, CreateUser or AddUserToTeam (likely having multiple services with closely related methods). The service would then shield the controller from retrieving/sending data to the repositories and using the UnitOfWork.
That way in your tests you would only need to mock IService.
For example a test for a typical "GET" action may look like:
//Arrange
var user = new User();
_mockServiceLayer.Setup(s => s.GetUser(123)).Returns(user);
//Act
var viewResult = _controller.GetUser(123) as ViewResult;
//Assert
Assert.AreEqual(user, viewResult.Model);
Hopefully this will help clarifying things a bit!
In the line that fails you are mocking the IService which does not have a constructor, so passing it args will cause it to fail. Since you are only trying to unit test the controller, you should change the line to this:
_mockServiceLayer = new Mock<IService>();
and then specify the the behaviors you want using _mockServiceLayer.Setup(...). Remember your interface doesn't know anything about your unit of work so you do not need to mock the unit of work.
If you actually want to test the controller and service layer together then you would do something like this:
_mockUnitOfWork = new Mock<IUnitOfWork>();
var serviceLayer = new Service(_mockUnitOfWork.Object);
var controller = new GameController(serviceLayer);
You would probably be better off unit testing the controllers and the serviceLayer separately, each time mocking the layer below.
I've been working on EF Repository pattern with Unit of Work and DI. I was following this example: link In example is used Unity as DI container, but I want to use Ninject.
(Note: with Unity everything works just fine).
So I've set up my Ninject Controller Factory like this: link.
When i go to my controller and try to list messages, it works fine but when i try to create message nothing happens, values are passed to controller and to repository, but data isn't saved to database for some reason.
Here is controller constructor:
private readonly IUserRepository _userRepository;
private readonly IMessageThreadRepository _messageThreadRepository;
public TetsController(IMessageThreadRepository messageThreadRepository, IUserRepository userRepository)
{
_messageThreadRepository = messageThreadRepository;
_userRepository = userRepository;
}
And here is code for messageThreadRepository which is being called by controller
public class MessageThreadRepository : RepositoryBase<MessageThread>, IMessageThreadRepository
{
private readonly RepositoryBase<MessageThread> _messageThreadRepository;
private readonly RepositoryBase<Message> _messageRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly UserRepository _userRepository;
public MessageThreadRepository(IUnitOfWork unitOfWork, RepositoryBase<MessageThread> messageThreadRepository,
IDatabaseContextFactory databaseContextFactory, UserRepository userRepository, RepositoryBase<Message> messageRepository)
: base(databaseContextFactory)
{
_unitOfWork = unitOfWork;
_messageThreadRepository = messageThreadRepository;
_userRepository = userRepository;
_messageRepository = messageRepository;
}
//some code here
// part with adding to database
Message message = messageFactory.CreateMessage(messageBody, userSender, messageThread);
_messageRepository.Add(message);
if (!doesThreadExist)
{
_messageThreadRepository.Add(messageThread);
}
_unitOfWork.Commit();
}
EDIT
I've tried to add User to database, but with no luck. Again I manage to fetch all users but I can't add them, here is User repository:
public class UserRepository : RepositoryBase<User>, IUserRepository
{
private readonly IUnitOfWork _unitOfWork;
private readonly RepositoryBase<User> _repository;
public UserRepository(IUnitOfWork unitOfWork, IDatabaseContextFactory databaseContextFactory, RepositoryBase<User> repository) : base (databaseContextFactory)
{
_unitOfWork = unitOfWork;
_repository = repository;
}
public User GetUserById(int id)
{
return _repository.GetSingleByCriteria(u => u.UserId.Equals(id));
}
public User GetUserByEmail(string email)
{
return _repository.GetSingleByCriteria(u => u.Email.Equals(email));
}
public User GetUserByUserName(string name)
{
return _repository.GetSingleByCriteria(u => u.UserName.Equals(name));
}
public void AddUser(User user)
{
_repository.Add(user);
_unitOfWork.Commit();
}
public IEnumerable<User> GetAllUsers()
{
return _repository.GetAll();
}
}
I assume you're using MVC since you reference an article about using it with MVC.
Did you do all the steps mentioned here?
http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/
Why are you using a custom controller factory instead of using the built-in dependency injection support of MVC, using Ninject.MVC3 package?
Im working on a C# Project that uses Entity Framework, Repository-Pattern, UnitOfWork-Pattern and Moq.
I´m new to EF and Unit Tests with Moq and got the following problem:
I get null pointers, when i try to test the methods from the service class...and it seems as if the context can´t get instantiated. Can anyone point my mistake out or provide me with a link?
Example:
portionService.cs
/// <summary>
/// The PortionService class represents a service for the Portion model.
/// </summary>
public class PortionService : Service, IPortionService
{
/// <summary>
/// In this constructor the base constructor of the Service class is called.
/// </summary>
/// <param name="context">Represents a context of the data access layer.</param>
public PortionService(IDALContext context) : base(context) { }
public void Add(Portion portion)
{
context.Portion.Create(portion);
context.SaveChanges();
}
public Portion GetPortionByName(string name)
{
return context.Portion.GetAll().Where(p => p.Name.ToUpper() == name.ToUpper()).LastOrDefault();
}
portionServiceTests.cs
// TestClass for PortionService-Tests
[TestClass]
public class PortionServiceTests
{
private PortionService _portionService;
// define the mock object
private Mock<IPortionService> _portionServiceMock;
[TestInitialize]
public void Init()
{
_portionService = new PortionService(new DALContext());
// create the mock object
_portionServiceMock = new Mock<IPortionService>();
}[TestMethod]
public void EnteringPortionNameReturnsThePortion()
{
//arrange
// arrange data
Portion portion = new Portion { PortionID = 12, Name = "testPortion" };
//arrange expectations
_portionServiceMock.Setup(service => service.GetPortionByName("testPortion")).Returns(portion).Verifiable();
//act
var result = _portionService.GetPortionByName("testPortion");
//verify
Assert.AreEqual(portion, result.Name);
}
DALContext.cs
public class DALContext : IDALContext, IDisposable
{
/// <summary>
/// The _context property represents the context to the current Database.
/// </summary>
private DatabaseContext _context;
private Repository<Portion> _portionRepository;
...
/// <summary>
/// In this constructor the single instance of the DataBaseContext gets instantiated.
/// </summary>
public DALContext()
{
_context = new DatabaseContext();
}
You are trying to verify the mock result to an actual data in the database, that's why it fails. Your unit test should test the service, and that the service calls the context, not the mock of the service itself.
The following example uses FakeDbSet approach from Rowan Miller's article.
using System.Data.Entity;
using System.Linq;
using Moq;
using NUnit.Framework;
using SharpTestsEx;
namespace StackOverflowExample.EntityFramework
{
public class DataEntity
{
public int Id { get; set; }
public string Data { get; set; }
}
public interface IContext
{
IDbSet<DataEntity> DataEntities { get; }
}
public class DataService
{
private IContext _db;
public DataService(IContext context)
{
_db = context;
}
public DataEntity GetDataById(int id)
{
return _db.DataEntities.First(d => d.Id == id);
}
}
[TestFixture]
public class DataServiceTests
{
[Test]
public void GetDataByIdTest()
{
//arrange
var datas = new FakeDbSet<DataEntity>
{
new DataEntity {Id = 1, Data = "one"},
new DataEntity {Id = 2, Data = "two"}
};
var context = new Mock<IContext>();
context.SetupGet(c => c.DataEntities).Returns(datas);
var service = new DataService(context.Object);
//act
var result = service.GetDataById(2);
//assert
result.Satisfy(r =>
r.Id == 2
&& r.Data == "two");
}
}
}
it's actually not easy to unit test EF based application. I would recommend using a library like effort to mock the entity framework.
I wanted to know if this was thread safe/ good practice. My IOC is ninject, everything service layer call is via the default setting (In transient scope I think?).
Question, is instantiating new FileAllocation(loggedonuser,_repo) correct? The best way? What is the best way to do this? This is a domain class that holds logic that could be called from various services, there are usually a few database calls involved, most of the time no persistance is necessary...
Anyway, I call my service method via an interface e.g.
void SaveFile(int reportid, stream file); //Interface name: IReportFileService
public Class FileService: Servicebase, IReportFileService
{
private readonly IRepoSession _repo;
public FileService(IUserSession user, IRepoSession repo, IUpdateSession update)
: base(user,update)
{
_repo = repo;
}
//save file if users 'counter' is ok..
public void SaveFile(int reportid, stream file)
{
//here I want to instantiate a new class that I store in my domain and store the counters
//etc and do related db calls to check up relevant values
//note loggedonuser is a prop on my *base class*
var userChecks = new FileAllocation(loggedonuser,_repo);
userChecks.CountEmUp(); //exception is thrown if 0, less than "limit" etc...
base.update(userChecks.mycompany); //persist
base.commit(); //base class method includes try, catch block...
}
}
public class FileAllocation
{
private readonly IRepoSession _repo;
private readonly Loggedonuser _user;
private int CompanyUploads;
private int UserUploads;
public Company mycompany;
public FileAllocation(Loggedonuser user, IRepoSession repo)
{
_repo = repo;
_user = user;
}
public void CountEmUp()
{
//do error checking,
//load up other tables can user upload - permissions, count is ok etc...
// check the upload type if of certain type we cannot proceed - call another method on this class
//set myCompany variable to new limits etc...
}
}
Base Service includes a prop, I dont want to instantiate this from other services i.e. more that once, how do I avoid that?
private LoggedonuserDTO _currentuser = null;
protected LoggedonuserDTO loggedonuser
{
get
{
if (_currentuser == null)
{
_currentuser = _user.GetCurrentUser(); //make db call here...
}
return _currentuser;
}
}
#Darin suggested:
public interface IFileAllocation
{
CountEmUp(Loggedonuser currentuser);
}
//pass in loggedonuser to any method that requires it...
public class FileAllocation: IFileAllocation
{
CountEmUp(Loggedonuser currentuser)
{
//do whatever here...
}
}
var userChecks = new FileAllocation(loggedonuser,_repo);
introduces a strong coupling between the FileService and the FileAllocation classes. If this is not a problem for you then you can leave it that way. Otherwise you could abstract the operations of this FileAllocation class into an interface and then inject it into FileService. This way the FileService is weakly coupled with FileAllocation and could be reused in different contexts and unit tested in isolation.