How to mock the dependency injection object in unit test - c#

My project requires unit testing. I am using constructor dependency injection in my controller. When I mock the injected dependency object in my unit testing project and call it in a test method. Returns null in all cases.
Controller Class:
public class Owner:Controller
{
private readonly IComRepository repository;
private readonly DbContext context;
public Owner(IComRepository repository, DbContext context)
{
this.repository=repository;
this.context=context;
}
[HttpGet("GetAllTypes")]
public async Task<IActionResult> GetAllTypes()
{
var ownerTypes=repository.GetTypes();
return Ok(ownerTypes);
}
}
My Repository Class
public Interface IComRepository
{
IList<Type> GetTypes();
}
public Class ComRepository : IComRepository
{
private readonly DbContext context;
public ComRepository(DbContext context)
{
this.context=context;
}
public IList<Type> GetTypes()
{
var allTypes= context.Types.ToList();
return allTypes;
}
}
Now I need to test the GetAllTypes methods in my controller class. My Test Class is below mentioned:
using moq;
[TestClass]
public Class OwnerTest
{
public OwnerTest()
{
var mockIcomrepo = new Mock<IComRepository>();
var mockDbcontext = new Mock<Dbcontext>();
OwnerController owner = new OwnerController(mockDbContext.Object, mockIcomrepo.Object);
}
[TestMethod]
public void GetTypes()
{
var allTypes= owner.GetAllTypes(); //It's not trigger to my controller
Assert.AreEqual(5,allTypes.count());
}
}
How can I do it? Any one know the answer for this question.

As #Nkosi mentioned you have to use moq setup. Define your mocks outside constructor and initalize them in test class's constructor.
using moq;
[TestClass]
public Class OwnerTest
{
private readonly IComRepository _mockRepository;
private readonly OwnerControler _ownerController;
//your mock data
private readonly IList<Type> mockData;
public OwnerTest()
{
_mockRepository= new Mock<IComRepository>();
_ownerController = new OwnerController(mockDbContext.Object, mockIcomrepo.Object);
mockData=new IList<Type>{"Data1","Data2","Data3","Data4","Data5"};
}
//choose better names for testing a method
//Naming convention like this MethodName_StateUnderTest_ExpectedResult;
[TestMethod]
public void GetAllTypes()
{
_mockRepository.Setup(p=>p.GetAllTypes()).Returns(mockData);
var result= _ownerController.GetAllTypes();
var okResult=Assert.IsType<OkObjectResult>(result)
var returnTypes=Assert.IsAssignableFrom<IList<Type>>(okResult.Value);
Assert.AreEqual(5,returnTypes.count());
}
}
Also, why you inject your dbcontext to controller?your repository should depend dbcontext not controller.

Related

DataService in Test env always return null when fetching InMemoryDb data

public class TestStartup : Startup
{
private readonly Mock<ICarService> _carServiceMock;
public TestStartup(IConfiguration configuration) : base(configuration)
{
_carServiceMock = new Mock<ICarService>();
}
public override void ConfigureMyServices(IServiceCollection services)
{
services.AddSingleton(_carServiceMock.Object);
}
public override void ConfigureDatabase(IServiceCollection services)
{
services.AddDbContext<CarContext>(options => options.UseInMemoryDatabase("CarDb"));
services.AddTransient<DataSeed>();
}
}
public class TestFixture: IDisposable, ICollectionFixture<TestFixture>
{
public TestFixture()
{
_server = new TestServer(new WebHostBuilder()
.UseStartup<TestStartup>()
.UseEnvironment("Development"));
_client = _server.CreateClient();
}
}
Inside Controller I'm using ICarService which is using CarContext to retrieve data from the Db.
public class CarController
{
private readonly ICarService _carService;
public CarController(ICarService carService)
{
_carService = carService;
}
[HttpGet]
public async Task<IActionResult> Get([FromRoute] int id)
{
var contact = await _carService.GetAsync(id); **// this is always null**
}
}
My question is:
Since this is an integration test, do I need to mock ICarService in the first place and if so, what I'm doing wrong here?
If you are testing how the CarService class interacts with the database then you shouldn't be mocking it.
What you want to do is use the real CarService implementation and let dependency injection add the InMemoryDatabase into that class as the CarContext parameter.
So, remove the Mock<ICarService> and register the real one instead.
Why is it returning null?
In you example, when you call the method _carService.GetAsync(id) it is calling the mock class. But you haven't Setup any methods on the mock so any calls will return null.
You need to add the following to cause the mocked method to return a value:
_carService.Setup(cs => cs.GetAsync(It.IsAny<int>()).Returns(1);
But this would not call the in memory database as you are using a mock for CarService.

C# Dependency injection duplicating

I'm making an ASP.NET Core Razor Pages web application. In my application I use the following code:
public class MyClass
{
private readonly ApplicationDbContext _dbContext;
private readonly ICalendarService _calendarService;
public MyClass(ApplicationDbContext dbContext, ICalendarService calendarService)
{
_dbContext = dbContext;
_calendarService = calendarService;
}
public void MyFunction()
{
// here I need to use _dbContext and _calendarService
}
But when I use this class I need to do the following:
public class MySecondClass
{
private ImportIntoCalendar ImportHintSchedule;
public MySecondClass()
{
MyClass= new MyClass(_dbContext, _calendarService);
}
// Do something with variable ImportHintSchedule
ImportHintschedule.Function()
}
Everytime I need to add the dbcontext and the calendarservice into the parameters. So both need to be available in the other class. This feels like I'm doing something stupid, like I'm duplicating the same step. Does anybody know a better way to do this. Or is this just fine?
Edit:
I have this line in my startup.cs
services.AddScoped<ICalendarService, CalendarService>();
In your ConfigureServices you can add the IOC scopes.
For example, something like this. I don't know all of your code so the is just an example.
services.AddScoped<ICalendarService, CalendarService>();
services.AddScoped<IApplicationDbContext, ApplicationDbContext>();
You can also add singletons if that meets your needs as well.
Here is an example singleton call I use in my application
services.AddSingleton<IRepository<BaseItem>>(x => new Repository<BaseItem>(Configuration["MongoConnection:DefaultConnection"]));
I would suggest to create an Interface of your class, something like:
public interface IMyClass {
void MyFunction();
}
Then, implement that in your class:
public class MyClass : IMyClass {
private readonly ApplicationDbContext _dbContext;
private readonly ICalendarService _calendarService;
public MyClass(ApplicationDbContext dbContext, ICalendarService calendarService)
{
_dbContext = dbContext;
_calendarService = calendarService;
}
public void MyFunction()
{
// here I need to use _dbContext and _calendarService
}
}
And the add that to injector:
public void ConfigureServices(IServiceCollection services)
{
// existing code
services.AddTransient<IMyClass, MyClass>();
}
and finally use IMyClass in Controller constructor.
public class MyController:Controller
{
private IMyInterface _myClass;
public MyController(IMyInterface myclass) {
_myClass = myClass;
}
public IActionResult MyAction() {
_myClass.MyFunction();
return View();
}
}

What is the best way to implement Dependency Injection in Base Controller

I have the follow trouble, in my base controller i do dependency injection. And i have a class child with implementation of base controller and i need pass the constructor. So my doubt is, my way to implementation of dependency injection is correctly?
If no, what is the best way to do this?
I use unity to implementate D.I, and my ide is VS2017 web api 2.
Follow this code i using:
Base controller or parent controller:
public class BaseController : ApiController
{
public string[] includes = null;
private readonly IFiltroServico servico;
public BaseController(IFiltroServico _servico)
{
servico = _servico;
}
}
Base controller to generics types implements Base Controller:
public abstract class BaseController<E, R, F> : BaseController
where E : class
where R : class
where F : class
{
private readonly IFiltroServico servico;
public AreaFormacaoController(IFiltroServico _servico): base(_servico)
{
servico = _servico;
}
}
Child controller:
public abstract class BaseController<R> : BaseController
where R : class
{
private readonly IFiltroServico servico;
public AreaFormacaoController(IFiltroServico _servico): base(_servico)
{
servico = _servico;
}
//services of controller;
}
You don't need to define the private field servico over and over again as it is already preset in the base controller. Just define it as protected readonly in the base class and use it in the childs.
Other than that your code is fine.
It is perfectly reasonable that a child has the same dependency parameters in the constructor as it inherits behavior of the base class that is most likely relying on the dependency.
Another option would be to use property injection in the base class but you need to add a unity specific attribute to the property. I don't like that as you bind your code directly to Unity.
Have you seen https://simpleinjector.org/index.html
check out git from https://github.com/simpleinjector/SimpleInjector
It is one of the best Inversion of Control library (IOC).
Only thing you need to do is register all your services and types.
using SimpleInjector;
static class Program
{
static readonly Container container;
static Program() {
// 1. Create a new Simple Injector container
container = new Container();
// 2. Configure the container (register)
container.Register<IOrderRepository, SqlOrderRepository>();
container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
container.Register<CancelOrderHandler>();
// 3. Verify your configuration
container.Verify();
}
static void Main(string[] args)) {
// 4. Use the container
var handler = container.GetInstance<CancelOrderHandler>();
var orderId = Guid.Parse(args[0]);
var command = new CancelOrder { OrderId = orderId };
handler.Handle(command);
}
}
Once you register all your types and services you can inject those services where ever you want
public class CancelOrderHandler {
private readonly IOrderRepository repository;
private readonly ILogger logger;
private readonly IEventPublisher publisher;
// Use constructor injection for the dependencies
public CancelOrderHandler(
IOrderRepository repository, ILogger logger, IEventPublisher publisher) {
this.repository = repository;
this.logger = logger;
this.publisher = publisher;
}
public void Handle(CancelOrder command) {
this.logger.Log("Cancelling order " + command.OrderId);
var order = this.repository.GetById(command.OrderId);
order.Status = OrderStatus.Cancelled;
this.repository.Save(order);
this.publisher.Publish(new OrderCancelled(command.OrderId));
}
}
public class SqlOrderRepository : IOrderRepository {
private readonly ILogger logger;
// Use constructor injection for the dependencies
public SqlOrderRepository(ILogger logger) {
this.logger = logger;
}
public Order GetById(Guid id) {
this.logger.Log("Getting Order " + order.Id);
// Retrieve from db.
}
public void Save(Order order) {
this.logger.Log("Saving order " + order.Id);
// Save to db.
}
}
Let me know if you have any queries, Thanks.

Unit testing web api using Entity Framework

Any better examples or tutorials available on Unit testing projects using Entity framework than this
http://www.asp.net/web-api/overview/testing-and-debugging/mocking-entity-framework-when-unit-testing-aspnet-web-api-2
In my case API project is using Entity framework file Edmx file and accessing the tables from the edmx file from Repository class. [ Not really like the codefirst or dbfirst approach ]
The structre of repo class looks like
public class AppBackendRepository
{
// modify the type of the db field
private AppDBEntities db_context = new AppDBEntities();
public List<Student> Get()
{
return db_context.Students.ToList();
}
}
public class StudentController
{
private static AppBackendRepository repo;
public StudentController()
{
repo = new AppBackendRepository();
}
public IEnumerable<Student> GetStudents()
{
List<Student> students = repo.Get();
return students;
}
}
How can i write a proper Unit testing against this way of code architecture
The quick answer is: You don't.
Now, I say this because I tend to regard "Unit Tests" as something that is quick and can be used in continuous integration, while "Integration tests" are the slow tests that only run at night and, of course, when you're working with them.
The problem you're creating here is that you're using untestable code.
Take your method, "GetStudents()" as an example. You're depending on the repo to actually exist before calling this method. Any unit-test will depend on Entity Framework being installed, AND of course, this will be super-slow. Imagine a few hundred of these, and your unit test framework is now a serious clog in your system that makes people say "IT's so slow that we don't use it"
A better approach would be to implement the Dependency Inversion Principle
First, define an interface:
public interface IStudentRepository
{
IEnumerable<Student> GetStudents();
}
Now, your class is just an implementation detail of that contract, for example:
public class StudentRepository : DbContext, IStudentRepository
{
private DbSet<Student> Students;
public IEnumerable<Student> GetStudents()
{
return Students;
}
}
In the class that uses your repository, you can now inject your instance by constructor injection, and end up with something that is fully unit-testable:
public class StudentEnrollment
{
private readonly IStudentRepository _studentRepository;
// Inject the contract here
public StudentEnrollment(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
public IEnumerable<Student> GetStudentsForClass(StudentClass studentClass)
{
return _studentRepository.GetStudents().Where(student => student.class == studentClass);
}
}
And now, as the added bonus, you can Unit-Test every last bit of logic, for example:
[TestMethod]
public void GetStudentsForClass_GetStudentsThrowsException_ResultIsNull()
{
// Arrange
var mock = Mock.Create<IStudentRepository();
var badException = new Exception("I'm bad");
mock.Setup(repo => repo.GetStudents()).Throws(badException);
var someClass = new StudentClass();
var instance = new StudentEnrollment(mock.object);
// Act
var result = instance.GetStudentsForClass(studentClass);
// Assert
result.ShouldBeEmpty();
}
I'm of the opinon that all your code should be tested. This way you can easily detect when some developer breaks an expected chain. Because of that I always add tests for both repositories and controllers. In your case I would add a test that ensures that your controller uses your repository in a correct way, and that your repository uses EF the right way. However, you should not test EF itself. That's Microsofts problem.
First you must abstract the DbContext.
public class YourContext : DbContext, IDbContext
{
public virtual IDbSet<Student> Students { get; set; }
}
public interface IDbContext
{
IDbSet<Student> Students;
}
// Util for creating a testable context.
public class ContextUtils
{
internal static IDbSet<T> GetMockDbSet<T>(IEnumerable<T> data) where T : class
{
IQueryable<T> queryable = data.AsQueryable();
IDbSet<T> dbSet = MockRepository.GenerateMock<IDbSet<T>, IQueryable>();
dbSet.Stub(m => m.Provider).Return(queryable.Provider);
dbSet.Stub(m => m.Expression).Return(queryable.Expression);
dbSet.Stub(m => m.ElementType).Return(queryable.ElementType);
dbSet.Stub(m => m.GetEnumerator()).Return(queryable.GetEnumerator());
return dbSet;
}
public static IDbContext GetMockDbContext()
{
var dbContext = MockRepository.GenerateMock<IDbContext>();
dbContext.Stub(x => x.Student).PropertyBehavior();
dbContext.Students = GetMockDbSet(GetStudents());
return dbContext;
}
private static IEnumerable<Student> GetStudents()
{
// Create some mock data.
return new List<Student>
{
new Student()
{
StudentID = 1,
Name = "Student One",
},
new Student()
{
StudentID = 2,
Name = "Student Two",
},
new Student()
{
StudentID = 3,
Name = "Student Three",
}
};
}
}
Now you have a DbContext that can be tested. More information regarding the mocking of DbContext can be found on this blog.
http://aikmeng.com/post/62817541825/how-to-mock-dbcontext-and-dbset-with-moq-for-unit
Then make sure that you can test your repository.
public class AppBackendRepository
{
private IDbContext _dbContext;
// With injection.
public AppBackendRepository(IDbContext context)
{
_dbContext = context;
}
public List<Student> Get()
{
return _dbContext.Students.ToList();
}
}
It can also be done with a factory.
public class AppBackendRepository
{
public List<Student> Get()
{
using (var context = DbContextFactory.GenerateContext())
{
return context .Students.ToList();
}
}
}
public interface IDbContextFactory
{
/// <summary>
/// Creates a new context.
/// </summary>
/// <returns></returns>
IDbContext GenerateContext();
/// <summary>
/// Returns the previously created context.
/// </summary>
/// <returns></returns>
IDbContext GetCurrentContext();
}
public class DbContextFactory : IDbContextFactory
{
private IDbContext _context;
public IDbContext GenerateContext()
{
_context = new DbContext();
return _context;
}
public IDbContext GetCurrentContext()
{
if (_context == null)
_context = GenerateContext();
return _context;
}
}
Now you can test the repository and make sure that it's using EF the right way.
[TestMethod]
public void ShouldReturnAllValues()
{
int correctAmount = 3; // The number specified in MockUtils.
var dbContext = MockUtils.GetMockDbSet();
var repo = new AppBackendRepository(dbContext);
var result = repo.Get();
Assert.IsTrue(result.Count() == correctAmount);
}
What you actually tested is that no developer broke the intended code with something like:
public class AppBackendRepository
{
private IDbContext _dbContext;
// With injection.
public AppBackendRepository(IDbContext context)
{
_dbContext = context;
}
public List<Student> Get()
{
// Only active...
return _dbContext.Students.Where(x => x.Active).ToList();
}
}
Now that you know that the repo is doing what it's supposed to, you can simply make sure that your controller is calling the repo and actually returns the value.
public class StudentController
{
private static IAppBackendRepository _repo;
public StudentController(IAppBackendRepository repo)
{
_repo = repo;
}
public IEnumerable<Student> GetStudents()
{
List<Student> students = _repo.Get();
return students;
}
}
[TestMethod]
public void ShouldCallRepo()
{
// With Rhino
var mockRepo = MockRepository.GenerateStub<IAppBackendRepository>();
var expectedResult = new List<Student>();
mockRepo.Expect(x => x.Get()).Return(expectedResult);
var controller = new StudentController(mockRepo);
var actualResult = controller.GetStudents();
mockRepo.VerifyAllExpectations();
Assert.AreEqual(actualResult, expectedResult); // Possible in it's own method.
}
What you actually tested here is that your controller doesn't manipulate the list before returning it, and that it's actually using the repo as intended.
Also, you might consider using an IoC like Structuremap or Unity. It makes it much easier to make testable applications.

How can I pass a mock object when I am doing setter injection in ASP.NET MVC Controller

Say, I have the below Controller
public class UsersController : Controller
{
private IUsersRepository UsersRepository { get; }
public UsersController()
{
UsersRepository = DependencyResolver.Current.GetService(typeof(IUsersRepository)) as IUsersRepository;
}
public ActionResult Index ()
{
MyUserDefinedModel data = UsersRepository.MyRepository();
return View(data);
}
}
Now I want to mock the IUsersRepository and pass it to the controller in my test script.
Below my test code
public class UsersListTest
{
private UsersController usersController = new Mock<IUsersRepository>();
private Mock<IUsersRepository> usersRepository = new UsersController();
[TestMethod]
public void TestMethod1()
{
//usersRepository.Setup(x => x.Get()).Returns(users);
}
}
As because private IUsersRepository UsersRepository { get; } private, I'm not able to pass the mock of IUsersRepository.
What would be the good idea to write unit test and mock in such case.
The reason that you have trouble with testing is because your Controller class uses the Service Locator anti-pattern. A Service Locator is a either a global instance (the DependencyResolver.Current) or an abstraction that allows resolving dependencies at runtime. One of the many downsides of the Service Locator is the problems it causes with testing.
You should move away from the Service Locator pattern and use dependency injection instead, favorably constructor injection. Your application components should have a single public constructor and those constructors should do nothing more than storing the incoming dependencies. This will result in the following UsersController implementation:
public class UsersController : Controller
{
private IUsersRepository usersRepository;
public UsersController(IUsersRepository usersRepository)
{
this.usersRepository = usersRepository;
}
public ActionResult Index()
{
return View(this.usersRepository.MyRepository());
}
}
With this in place, unit testing became trivial:
public class UsersControllerTests
{
[TestMethod]
public void Index_Always_CallsRepository()
{
// Arrange
var repository = new Mock<IUsersRepository>();
var controller = CreateValidUsersController(repository.Instance);
// Act
var result = controller.Index();
// Assert
Assert.IsTrue(repository.IsCalled);
}
// Factory method to simplify creation of the class under test with its dependencies
private UsersController CreateValidUsersController(params object[] deps) {
return new UsersController(
deps.OfType<IUsersRepository>().SingleOrDefault() ?? Fake<IUsersRepository>()
// other dependencies here
);
}
private static T Fake<T>() => (new Mock<T>()).Instance;
}
This does however, force you to change MVC's default IControllerFactory, since out-of-the-box, MVC can only handle controllers with a default constructor. But this is trivial and looks as follows:
public sealed class CompositionRoot : DefaultControllerFactory
{
private static string connectionString =
ConfigurationManager.ConnectionStrings["app"].ConnectionString;
protected override IController GetControllerInstance(RequestContext _, Type type) {
if (type == typeof(UsersController))
return new UsersController(new UsersRepository());
// [other controllers here]
return base.GetControllerInstance(_, type);
}
}
Your new controller factory can be hooked into MVC as follows:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start() {
ControllerBuilder.Current.SetControllerFactory(new CompositionRoot());
// the usual stuff here
}
}
You can find a more complete example here.
You could add a constructor that allows you to supply a mock of IUsersRepository. Your default constructor would call this with the instance from the DependencyResolver, like this:
public class UsersController : Controller
{
private IUsersRepository UsersRepository { get; }
public UsersController(IUsersRepository usersRepository)
{
UsersRepository = usersRepository;
}
public UsersController():this(DependencyResolver.Current.GetService(typeof(IUsersRepository)) as IUsersRepository)
{
}
public ActionResult Index ()
{
MyUserDefinedModel data = UsersRepository.MyRepository();
return View(data);
}
}

Categories