Moq, TDD and multiple layers - asp.net-mvc-3

I have a data assembly which defines my repositories.
I then have a service assembly which defines my services, each service has a repository injected into the constructor by Ninject.
When I'm unit testing my service methods, everything is fine:
[TestClass]
public class UserTests
{
IQueryable<User> users;
int userID;
public UserTests()
{
users = new List<User>()
{
new User { EmailAddress = "known#user.com", Password = "password", ID = 1}
}.AsQueryable();
}
[TestMethod]
public void Known_User_Can_Login()
{
// Arrange
var repository = new Mock<IUserRepository>();
var service = new UserService(repository.Object);
repository.Setup(r => r.GetAll())
.Returns(users);
// Act
bool loggedIn = service.UserLogin("known#user.com", "password", out userID);
// Assert
Assert.IsTrue(loggedIn);
Assert.AreEqual(1, userID);
}
[TestMethod]
public void Unknown_User_Cannot_Login()
{
// Arrange
var repository = new Mock<IUserRepository>();
var service = new UserService(repository.Object);
repository.Setup(r => r.GetAll())
.Returns(users);
// Act
bool loggedIn = service.UserLogin("unknown#user.com", "password", out userID);
//
Assert.IsFalse(loggedIn);
}
}
However, I'm running into problems when testing my controller (another level down).
My controller has dependencies on a service, and the service depends on a repository. I can't seem to get my controller tests to work. Here's what I have so far:
[TestClass]
public class AccountTests
{
IQueryable<User> users;
public AccountTests()
{
users = new List<User>()
{
new User { CompanyId = 1, EmailAddress = "known#user.com", Password = "password"},
new User { CompanyId = 1, EmailAddress = "unknown#user.com", Password = "password"}
}.AsQueryable();
}
[TestMethod]
public void Known_User_Can_Login()
{
int userID = 0;
var repo = new Mock<IUserRepository>();
// Arrange
var service = new Mock<UserService>(repo.Object);
var controller = new AccountController(service.Object);
// Act
var result = controller.Login(new LoginModel { EmailAddress = "known#user.com", Password = "password" }) as RedirectToRouteResult;
// Assert
service.Verify(x => x.UserLogin("known#user.com", "password", out userID), Times.Once());
Assert.AreEqual("Index", result.RouteValues["Action"]);
}
}
I keep getting an error about instantiating the UserService (i'm attempting to pass an instance of the UserRepository to it but it isn't working).
I must be doing something daft, but what?

Make sure that UserService is an interface.
Also, you must not create an instance of IUserRepository in your second test as you are doing here:
var repo = new Mock<IUserRepository>();
// Arrange
var service = new Mock<UserService>(repo.Object);
Since UserService is mocked, it will not make calls to IUserRepository anyway and you don't have to supply it's dependencies when creating the mock.
What you need to do is simply create the mock for UserService this way:
var service = new Mock<UserService>();
Even tough UserService normally has a dependency on a repository, Moq will just supply canned responses to methods and thus won't need to make the calls to the an actual repository.

UserService class I am guessing is not an interface or an abstract class, if not then it is bound to fail since Mock cannot create an implementation of the UserService. Thus either create an interface for UserService or define it as an abstract class or instantiate it as follows:
var service = new UserService(repo.Object);
or you could use Mock.Create<UserService>() but you need to have provided all the implemenation UserService needs using Mock.Provide<T>() api.
Hope this helps.
If this isnt the problem please update the question with the classes for UserService and your repository

Related

Convert Long id to Set list using Mapstruct?

In a Mapstruct interface, how can I convert an id to a Set< UserSystem > ?
I tried as follows but unsuccessfully because error occurs:
#Mapper(componentModel = "spring", uses = {UserSystemService.class})
public interface CompanyPostMapper extends EntityMapper<CompanyPostDTO, Company> {
#Mapping(source = "userSystemId", target = "userSystems", expression = "java(userSystemService.findByIdAndAddToSet(id))")
Company toEntity(CompanyPostDTO dto);
default Company fromId(Long id) {
if (id == null) {
return null;
}
Company company = new Company();
company.setId(id);
return company;
}
}
I don't know if I understood the use of the "uses" parameter correctly, but basically I would like to get the ID and query the register and return a Set with the register.
I was going to try "qualifiedByName" and create a method in the Mapper interface, but I don't know how I can inject the Repository and I don't know if that would be a good practice.
What would be the best way to solve?
MapStruct is a mapping framework. You are doing a lookup inside the mapping. It is possible of course (look at the JPA mapping example where an #Context is used). But you can't inherit EntityMapper<CompanyPostDTO, Company> at the same time.
Normally, you need to take the lookup outside your mapping logic and use an update method to update the object.
Your mapping would then look like:
#Mapper(componentModel = "spring" )
public interface CompanyPostMapper {
void updateEntity(CompanyPostDTO dto, #MappingTarget Company entity);
}
// and your call would look like:
public class CallingService{
Company company = userSystemService.findByIdAndAddToSet(id));
if (company == null) {
company = new Company();
}
companyPostMapper.updateEntity(dto, company);
}

Access Thread.CurrentPrincipal when binding with NInject in Owin context

I need to access my claims when binding my services, but appears that Ninject bind occurs before HttpMessageHandlerAdapter sets the Thread.CurrentPrincipal so I cannot access my claims when I'm binding my services. I tried this
kernel.Bind<IMyService>().ToMethod(x => GetMyService());
private static IMyService GetMyService()
{
var principal = Thread.CurrentPrincipal;
var userId = [GetUserIdFromPrincipalClaims]
return new MyService(userId);
}
But the claims list is empty, if I access Thread.CurrentPrincipal claims list from any action I can get an userId. How can I access my claims list when binding?
Since identity claims are a run-time value, I would say it can't be done (easily). However, one approach involving the decorator pattern and an abstract factory might look like this:
class MyServiceDecoraptor : IMyService
{
private readonly IMyServiceFactory _myServiceFactory;
public MyServiceDecoraptor(IMyServiceFactory myServiceFactory)
{
_myServiceFactory = myserviceFactory
}
public void MyServiceMethod()
{
var principal = Thread.CurrentPrincipal;
var userid = GetUserId(principal);
_myServiceFactory.Create(userid).MyServiceMethod();
}
//more code here
}

load repository with constructor parameters in Web API (1)

I'm trying to get the following scenario using autofac but I'm not sure how my code will be built to get this up & running.
I have a repository class, this repository class needs to get a project key (string) on initialization (constructor). I want to instantiate this repository in initialization of my "Initialize" method provided to my by Web Api, because the project key will be available in my route.
so instead of calling "new ProductRepository(projectKey)", I want to use Autofac. Can someone point me in the right direction? I didn't find any way to send in specific data to the container in web api, since the container/builder is only available in the appStart.
Should I make the container available as a singleton so that I can approach it, or is this bad practice?
in your initialization code:
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
in your controller:
public class MyController : ApiController
{
public MyController(IComponentContext container)
{
var key = new NamedParameter("projectKey", "keyFromRoute");
var repository = container.Resolve<ProductRepository>(key);
}
}
That should do it.
There is a nuget package that provides a DependencyResolver for WebApi that integrates with AutoFac. Create the DependencyResolver, assign it to the config, register your controllers in the autofac container.
I'm making some assumptions because you didn't provide your code, but I think you have something like this:
public class ProductRepository
{
public ProductRepository(DbContext dbContext, int projectKey)
{
}
}
public class SomeController : Controller
{
private readonly Func<int, ProductRepository> _repoFactory;
public SomeController(Func<int, ProductRepository> repoFactory)
{
_repoFactory = repoFactory;
}
public void DoStuff(int projectKey)
{
var repo = _repoFactory(projectKey);
repo.DoStuff();
}
}
public class RepositoryModule : Module
{
public override Load(ContainerBuilder builder)
{
builder.RegisterType<ProductRepository>();
}
}

How should you unit test with repository classes in MVC3?

I'm trying to do a test on my controllers which get data from repository classes.
This is the part of the repository I want to test:
public class NewsRepository
{
public IEnumerable<NewsItem> GetNews()
{
var result = (from n in n_db.NewsItems
orderby n.ID descending
select n).Take(3);
return result;
}
}
Just some small code to get how the testing works.
In my HomeController I've got this code inside the Index():
public ActionResult Index()
{
ViewBag.Message = "Announcements";
NewsRepository n_rep = new NewsRepository();
var model = i_rep.GetNews();
return View(model);
}
I am completely new to testing so all explanations would be great.
Thanks.
Your controller is impossible to be unit tested in isolation because it is strongly coupled with your repository on the following line:
NewsRepository n_rep = new NewsRepository();
You have simply hardcoded a specific implementation of the repository and in your unit test you cannot mock it. In order to do this properly you should start by defining an abstraction over this repository:
public interface INewsRepository
{
IEnumerable<NewsItem> GetNews();
}
and then have your specific repository implement this interface:
public class NewsRepository : INewsRepository
{
...
}
Ok now that we have an abstraction let's weaken the coupling between your data access and controller logic by using this abstraction:
public class NewsController: Controller
{
private readonly INewsRepository repository;
public NewsController(INewsRepository repository)
{
this.repository = repository;
}
public ActionResult Index()
{
ViewBag.Message = "Announcements";
var model = this.repository.GetNews();
return View(model);
}
}
Alright, now you have a controller that is no longer tightly coupled with some specific implementation. You could pickup your favorite mock framework and write a unit test. For example with NSubstitute here's how the unit test for the Index action might look like:
[TestMethod]
public void Index_Action_Fetches_Model_From_Repo()
{
// arrange
var repo = Substitute.For<INewsRepository>();
IEnumerable<NewsItem> expectedNews = new[] { new NewsItem() };
repo.GetNews().Returns(expectedNews);
var sut = new NewsController(repo);
// act
var actual = sut.Index();
// assert
Assert.IsInstanceOfType(actual, typeof(ViewResult));
var viewResult = actual as ViewResult;
Assert.AreEqual(expectedNews, viewResult.Model);
}
And that's pretty much it. Your controller is now easily unit testable in isolation. You don't need to be setting up databases or whatever. That's not the point to test the controller logic.

asp.net mvc repository pattern with service layer, when to mix entities in the repositories?

I'm building a new project off the service repository pattern detailed here. It seems to work well in the most basic of examples. In more complex scenarios is it acceptable to mix the objects in the service \ repository layers?. For example say there is a User repository and service and I want to be able to create an audit for the creation of a user, I would think this would go in the service layer.
If I follow the article the service automatically creates the user repository object in the constructor. Adding a audit would mean adding audit CRUD methods to the user repository? Does that make sense to do that?
public UserService(IValidationDictionary validationDictionary, IUserRrepository repository)
{
_validatonDictionary = validationDictionary;
_repository = repository;
}
in my experience you dont need repositories for each entity type. Just create one repository for the whole model, and then use linq queries over it. EF already provides implementation of that repository, you can create a custom interface like shown below and implement it over that repository ..
public interface IDataContext
{
void Add<T>(T entity) where T : BaseEntity;
void Delete<T>(T entity) where T : BaseEntity;
IQueryable<T> Find<T>(Expression<Func<T, bool>> where) where T : BaseEntity;
int SaveChanges()
}
where your base entity is your base class for all repositories.
most of the linq you would write would be pretty straighforward, but for the complicated ones, just write Utility classes
in our implementation the class derived from DbContext implements this interface, and all the auditing is done through the Save Method using the ChangeTracker
A sample implementation of EF 4.2 is below ...
public class MyContext : DbContext, IDataContext
{
static MyContext ()
{
Database.SetInitializer<MyContext >(null);
}
public T GetById<T>(int id) where T : BaseEntity
{
return this.Set<T>().SingleOrDefault(i => i.Id == id);
}
public void Add<T>(T entity) where T : BaseEntity
{
this.Set<T>().Add(entity);
}
public void Delete<T>(T entity) where T : BaseEntity
{
this.Set<T>().Remove(entity);
}
public IQueryable<T> Find<T>(System.Linq.Expressions.Expression<Func<T, bool>> where) where T : BaseEntity
{
return this.Set<T>().Where(where);
}
public override int SaveChanges()
{
this.SetAuditValues();
return base.SaveChanges();
}
private void SetAuditValues()
{
var addedEntries = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Added);
var currentUser = this.GetCurrentUser();
foreach (var addedEntry in addedEntries)
{
var entity = addedEntry.Entity as BaseEntity;
if (entity != null)
{
entity.CreateDateTime = DateTime.Now;
entity.CreateUser = currentUser;
entity.ModDateTime = DateTime.Now;
entity.ModUser = currentUser;
}
}
var modifiedEntries = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Modified);
foreach (var modEntry in modifiedEntries)
{
var entity = modEntry.Entity as BaseEntity;
if (entity != null)
{
entity.ModDateTime = DateTime.Now;
entity.ModUser = currentUser;
}
}
}
}
You can surely have one repository/service layer handle more than one entity if it falls within the purpose or domain of that service. Generally in simple examples - you are correct, you don't see this but there is no reason you can include another entity.
Now in regards to your audit, why not just call off to your audit service layer instead of including an audit object (if thats what you meant)

Resources