controller mvc3 unit test - asp.net

How to write unit test for
public ActionResult Details()
{
EmployeeDTO employee = this.EmployeeService.GetLoggedInEmployee();
EmployeeModel model = assembler.ToEmployeeModel(employee);
model.Title = GetEmployeeNameTitle(employee);
model.Controller = "LoanProcessor";
model.SelectedTab = MainNavTabs.LoanProcessor;
return View(model);
}
I have no idea how to solve it.

To make your code testable, you should inject dependencies to controller (it's not clear from this piece of code if you passing dependencies to controller, or instantiate them directly). Also you should make your controller to depend on abstractions (preferably interfaces) rather than concrete implementations.
EmployeeService should implement this interface:
public interface IEmployeeService
{
EmployeeDTO GetLoggedInEmployee();
// other methods of service
}
Then you make your controller depending on abstraction (only one dependency shown here for sample):
public class FooController : Controller
{
private IEmployeeService _employeeService;
public FooController(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
}
Now you can mock dependencies and start writing tests for controller (sample with NUnit and Moq):
[Test]
public void ShouldProvideEmployeeDetails()
{
// Arrange
EmployeeDTO bob = new EmployeDTO("Bob", 42);
Mock<IEmployeeService> employeeService = new Mock<IEmployeeService>();
employeeService.Setup(s = s.GetLoggedInEmployee()).Returns(bob);
FooController controller = new FooController(employeeService.Object);
// Act
var result = controller.Details() as ViewResult;
// Assert
EmployeeModel model = result.ViewData.Model;
Assert.That(model.Title, Is.EqualTo("Bob"));
Assert.That(model.Controller, Is.EqualTo("LoanProcessor"));
}
Then write code to pass this test.
You can read more on TDD here.

Related

Configuring Automapper in a .NET Core Console App with a data library?

I'm very new to AutoMapper, .NET Core and DI - although I am familiar with .NET Framework. I'm struggling to get AutoMapper to work in an app I've built. The app is a console app, which has a data library attached to it.
I've tried to configure AutoMapper in the Main() method of the console app - because as I understand it you need to configure it at the startup point of the app? I'm then creating an instance of a class in the data library which then in turn creates an instance of the Mappers class where I do all my mappings. I'm not sure if I've setup everything correctly and if I have I'm not sure what to pass to the constructor in the Mappers class to make it all work?
Console:
class Program
{
static void Main()
{
var services = new ServiceCollection();
services.AddAutoMapper(typeof(AutoMapping));
Learner learner = new Learner();
}
}
class AutoMapping : Profile
{
public AutoMapping()
{
CreateMap<LearnerDTO, LearnerModel>();
}
}
Learner Class (in my DataLibrary):
public class Learner
{
public string GetLearner()
{
Mappers mappers = new Mappers(); //This Mappers instance is underlined red
LearnerDTO learnerDTO = JsonFactory.LoadJson();
LearnerModel learnerModel = mappers.LearnerDTOtoLearnerModel(learnerDTO);
}
}
Mappers Class:
public class Mappers
{
private IMapper _mapper;
public Mappers(IMapper mapper)
{
_mapper = mapper;
}
public LearnerModel LearnerDTOtoLearnerModel(LearnerDTO learnerDto)
{
LearnerModel model = _mapper.Map<LearnerModel>(learnerDto);
return model;
}
}
Firstly, I would like some comment on whether I've configured AutoMapper correctly and in the right place? And secondly, if it all looks fine, what do I need to pass into the Mappers constructor from the Learner class when creating an instance?
If using dependency injection, then the classes should be refactored to allow for that using service abstractions and explicitly dependency principle via constructor injection.
Learner class and abstraction
public interface ILearner {
string GetLearner();
}
public class Learner : ILearner {
private readonly IMappers mappers;
public Learner(IMappers mappers) {
this.mappers = mappers;
}
public string GetLearner() {
LearnerDTO learnerDTO = JsonFactory.LoadJson();
LearnerModel learnerModel = mappers.LearnerDTOtoLearnerModel(learnerDTO);
}
}
Mappers class and abstraction
public interface IMappers {
LearnerModel LearnerDTOtoLearnerModel(LearnerDTO learnerDto);
}
public class Mappers : IMappers {
private readonly IMapper _mapper;
public Mappers(IMapper mapper) {
_mapper = mapper;
}
public LearnerModel LearnerDTOtoLearnerModel(LearnerDTO learnerDto) {
LearnerModel model = _mapper.Map<LearnerModel>(learnerDto);
return model;
}
}
Everything should then be registered with the dependency container, which will be used to resolve the services and perform the desired function.
Console
class Program {
static void Main() {
var services = new ServiceCollection();
services.AddAutoMapper(typeof(AutoMapping));
//use the lifetime that suits your needs
//but for this example I am using transient
services.AddTransient<ILearner, Learner>();
services.AddTransient<IMappers, Mappers>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
ILearner learner = serviceProvider.GetRequiredService<ILearner>();
//...
}
}

Create/Get DefaultHtmlGenerator from MVC Controller

I am trying to create(Or get an instance of it somehow) for Microsoft.AspNet.Mvc.Rendering.DefaultHtmlGenerator inside my MVC6 controller method
I wanted to generate the html for validation for my Model my self inside my controller of asp.net mvc. My issue is where to get the constructor data for DefaultHtmlGenerator like antiforgery, metadataProvider..etc
[HttpGet]
public IActionResult GetMarkup()
{
// IHtmlGenerator ge = this.CurrentGenerator();
IHtmlGenerator ge = new DefaultHtmlGenerator(params);
var tag= ge.GetClientValidationRules(params)
}
here is the a link about the HtmlGenerator class
DefaultHtmlGenerator
Since MVC 6 is based on dependency injection, all you have to do is require IHtmlGenerator in your constructor, and the DI container will automatically fill in all of the dependencies of DefaultHtmlGenerator (provided that is what is setup in your DI configuration).
public class HomeController : Controller
{
private readonly IHtmlGenerator htmlGenerator;
public HomeController(IHtmlGenerator htmlGenerator)
{
if (htmlGenerator == null)
throw new ArgumentNullException("htmlGenerator");
this.htmlGenerator = htmlGenerator;
}
public IActionResult GetMarkup()
{
// Use the HtmlGenerator as required.
var tag = this.htmlGenerator.GetClientValidationRules(params);
return View();
}
}
That said, it appears that the GetClientValidationRules method is only designed to work within a view, since it accepts ViewContext as a parameter. But this does answer the question that you asked.

Unity injection of an instance inside WebAPI action

I am stuck with this and I wonder what is the best way to approach this problem. I have a WebApi controller where I want to inject ICommand instance but I can know what is the instance I need once I inspect the Post request data. I'll give an example to be more clear but my question also applies to Winform events where you receive an event argument and depending of this event arg you want to have different implementation injected.
public class TestController : ApiController
{
public object Post(int id)
{
ICommand command = null;
if(id = 1)
{
command = new Id1Command();
}
else
{
command = new Id2Command();
}
return new object();
}
}
The only thing I can think of is creating a factory that accepts unity container as argument and inside that factory to call container.Resolve with named instance.
My problem with that is that I am taught that you shouldn't register or resolve outside your composition root and that is violation of the good practices (according Mark Seemann). I am looking for the best design for this problem in general.
I would use a CommandFactory and pass it to the TestController:
public class TestController : ApiController
{
private readonly ICommandFactory mCommandFactory;
public TestController(ICommandFactory CommandFactory)
{
mCommandFactory = CommandFactory;
}
public object Post(int id)
{
ICommand command = null;
if(id = 1)
{
command = CommandFactory.CreateId1Command();
}
else
{
command = CommandFactory.CreateId2Command();
}
return new object();
}
}
Now you have to make sure that Unity is creating the TestController. To do so, you have to implement, configure and set an IDependencyResolver. Check Dependency Injection in ASP.NET Web API 2.
Edit to your comment:
For this scenario you can use an autofactory using a functor that takes an int:
public class TestController : ApiController
{
private readonly Func<int, ICommand> mCommandFactory
public TestController(Func<int, ICommand> CommandFactory)
{
mCommandFactory = CommandFactory;
}
public object Post(int id)
{
var command mCommandFactory(id);
return new object();
}
}
The registration should look like this:
container.RegisterType<Func<int, ICommand>>(new InjectionFactory(
c => new Func<int, ICommand>(
id =>
{
if (id == 1)
{
return new Command();
}
else
{
return new Command2();
}
})));
Note: You still have to set the DependencyResolver!

Registration by convention and interception causes ResolutionFailedException

Simple scenario
public interface IFoo
{
int GetData();
}
public class Foo : IFoo
{
[CacheResult]
public int GetData() { .... }
}
public class MyController
{
[Dependency]
IFoo Foo {get; set;}
}
If I register the interface manually, resolving MyController works fine:
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager(),
new InterceptionBehavior<PolicyInjectionBehavior>(),
new Interceptor<InterfaceInterceptor>());
var controller = container.Resolve<MyController>();
If I try to use auto-registration:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled,
getInjectionMembers: t => new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<PolicyInjectionBehavior>(),
});
var controller = container.Resolve<MyController>();
The resolve fails with a ResolutionFailedException because the Type passed must be an interface. Of course, if I make it an interface, it will work, but only if it is named Controller. If I call it, MyController or SqlController or whatever, then the mapping fails because it cannot resolve the interface.
I was hoping to just do an assembly scan, similar to what the Spring framework does, but I have not been able to figure it out.
What am I missing? Or is this not possible in Unity?
The problem is that AllClasses.FromLoadedAssemblies is matching and registering your controller as well. Then when Unity tries to resolve the controller (not IFoo), it finds that the controller is not registered with an interface.
Here's a helper that will reduce your registrations to only those classes that have a matching interface.
public static class TypeFilters
{
public static IEnumerable<Type> WithMatchingInterface(this IEnumerable<Type> types)
{
return types.Where(type =>
type.GetTypeInfo().GetInterface("I" + type.Name) != null);
}
}
and then you can use this to modify your registration like so...
AllClasses.FromLoadedAssemblies().WithMatchingInterface()

ASP.Net MVC TDD using Moq

I am trying to learn TDD/BDD using NUnit and Moq.
The design that I have been following passes a DataService class to my controller to provide access to repositories.
I would like to Mock the DataService class to allow testing of the controllers.
There are lots of examples of mocking a repository passed to the controller but I can't work out how to mock a DataService class in this
scenerio.
Could someone please explain how to implement this?
Here's a sample of the relevant code:
[Test]
public void Can_View_A_Single_Page_Of_Lists()
{
var dataService = new Mock<DataService>();
var controller = new ListsController(dataService);
...
}
namespace Services
{
public class DataService
{
private readonly IKeyedRepository<int, FavList> FavListRepository;
private readonly IUnitOfWork unitOfWork;
public FavListService FavLists { get; private set; }
public DataService(IKeyedRepository<int, FavList> FavListRepository,
IUnitOfWork unitOfWork)
{
this.FavListRepository = FavListRepository;
this.unitOfWork = unitOfWork;
FavLists = new FavListService(FavListRepository);
}
public void Commit()
{
unitOfWork.Commit();
}
}
}
namespace MyListsWebsite.Controllers
{
public class ListsController : Controller
{
private readonly DataService dataService;
public ListsController(DataService dataService)
{
this.dataService = dataService;
}
public ActionResult Index()
{
var myLists = dataService.FavLists.All().ToList();
return View(myLists);
}
}
}
Create an interface like this:
public interface DataService
{
FavListService FavLists { get; }
void Commit();
}
Make your DataService implement this interface and your controller should depend on this interface. Problem solved :)
EDIT: This line of code:
dataService.FavLists.All().ToList();
is breaking the law of demeter and will be a pain to unit test your service. Create a method like AllFavList() on your service instead of all these chain of calls, it will be easier to mock.
EDIT2: How to mock you get property
dataService.SetupGet(d => d.FavLists).Returns(your_variable);

Resources