I am using nuit with moq to test my controllers.
I use a session class which has an interface and an HttpContext is injected into the constructor using ninject.
like this
public class SessionService : ISession
{
public HttpContext Context { get; set; }
public SessionService(HttpContext context)
{
this.Context = context;
}
}
public interface ISession
{
HttpContext Context { get; set; }
}
public HomeController(ISession session)
{
_session = session;
}
I think in order to test the controller I have mock the HttpContext first and then pass that object into the the construtor of the mocked ISession.
I have this so far
[Test]
public void index_returns_view()
{
//arrange
var mockHttpContext = new Mock<HttpContext>();
var mockContext = new Mock<ISession>(mockHttpContext);
var c = new HomeController(mockContext.Object);
//act
var v = c.Index() as ViewResult;
//assert
Assert.AreEqual(v.ViewName, "Index", "Index View name incorrect");
}
which builds but nunit returns the following error when the test is run
System.NotSupportedException : Type to mock must be an interface or an abstract or non-sealed class.
Thanks for all help.
Have your session take a HttpContextBase in the constructor and use that as the type of the property.
You should still be able to pass a concrete HttpContext the the session in production code.
public class SessionService : ISession
{
public HttpContextBase Context { get; set; }
public SessionService(HttpContextBase context)
{
this.Context = context;
}
}
Then fix your unit test by passing "mockHttpContext.Object" to the session constructor and that it mocks the HttpContextBase.
[Test]
public void index_returns_view()
{
//arrange
var mockHttpContext = new Mock<HttpContextBase>();
var mockContext = new Mock<ISession>(mockHttpContext.Object);
var c = new HomeController(mockContext.Object);
//act
var v = c.Index() as ViewResult;
//assert
Assert.AreEqual(v.ViewName, "Index", "Index View name incorrect");
}
Related
I'm trying to mock using Moq, xUnit,.Net 6, Entity framework Core, I have this service:
public class CompanyService : ICompanyService
{
private readonly ICompanyRepository _repository;
public CompanyService(ICompanyRepository repository)
{
_repository = repository;
}
public async Task<Company> Create(Company Company) => await _repository.Create(Company);
}
this is the company service interface:
public interface ICompanyService
{
Task<Company> Create(Company Company);
}
this is my company repository class:
public class CompanyRepository : ICompanyRepository
{
private readonly ApplicationDbContext _context;
public CompanyRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<Company> Create(Company Company)
{
Company.Id = Guid.NewGuid();
await _context.Companies.AddAsync(Company);
await _context.SaveChangesAsync();
return Company;
}
}
and this is its interface:
public interface ICompanyRepository
{
Task<Company> Create(Company Company);
}
this is my DbContext:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options): base(options)
{}
public DbSet<Company> Companies { get; set; }
}
and finally this is my class for testing:
public class CompanyServiceTest
{
private readonly CompanyService _sut;
private readonly Mock<ICompanyRepository> _companyRepositoryMock = new Mock<ICompanyRepository>();
public CompanyServiceTest()
{
_sut = new CompanyService(_companyRepositoryMock.Object);
}
[Fact]
public async void CreateACompanyShouldWorks()
{
//Arrange
var CompanyEntity = new Company();
CompanyEntity.Name = "Test Company";
//Act
var companyCreated = await _sut.Create(CompanyEntity);
//Assert
Assert.NotNull(companyCreated);
_companyRepositoryMock.Verify(r => r.Create(CompanyEntity));
}
}
but when I run the test I get this message error:
"Assert.NotNull() Failure"
Stack Trace:
CompanyServiceTest.CreateACompanyShouldWorks() line 31
<>c.b__128_0(Object state)
I don't know if I have to mock the ApplicationDbContext, or if I have to mock anything else, I'm Using xUnit, .Net 6, Entity framework core, also I have downloaded the Moq package.
You just forgot to setup the mock inside the Arrange phase
_companyRepositoryMock
.Setup(r => r.Create(It.IsAny<CompanyEntity>()))
.ReturnsAsync(expectedCompany);
OR
_companyRepositoryMock
.Setup(r => r.Create(It.IsAny<CompanyEntity>()).Result)
.Returns(expectedCompany);
If you don't setup the mock then it will return the default value.
If you change the MockBehaviour to strict then it will throw exception.
UPDATE #1
in the case of the method GetAllCompanies I have to create a List<Company>() and then return them ? and in the method GetCompanyById I have to create an object of Company and returns it ? I mean xUnit does not go to the database using my repository?
The short answer is yes you have to mock all the methods that you want to use on your dependency. Since the CompanyService is relying correctly on abstraction (ICompanyRepository interface) rather than on the implementation (CompanyRepository class) that's why you are not depending on the Entity Framework directly.
If you want to test your repository tier/layer/module than you have to mock the DbContext to avoid database calls. There are tons of nuget packages which can be used to ease the mocking burden.
This is the solution:
//Arrange
var CompanyEntity = new Company();
CompanyEntity.Name = "Test Company";
CompanyEntity.Id = Guid.NewGuid();
CompanyEntity.Employees = new HashSet<Employee>();
//arrange
_companyRepositoryMock
.Setup(r => r.Create(It.IsAny<Company>()))
.ReturnsAsync(CompanyEntity);
//Act
var companyCreated = await _sut.Create(CompanyEntity);
//Assert
Assert.NotNull(companyCreated);
_companyRepositoryMock.Verify(r => r.Create(companyCreated));
I am trying to understand how mocking works in Xunit with AutoFixture. I have created Service and Repository classes and their interfaces. Mocked method should pass value which is different from default value.
Mocked method always pass default values instead of values which i am writing in ".Returns()". I have tried AutoConfiguredMoqCustomization but it provides completely random values which i can't get back.
Repository.cs
public class Repository : IRepository
{
public int GetInt()
{
return 999;
}
}
Service.cs
public class Service : IService
{
private readonly Repository _repository;
public Service()
{
_repository = new Repository();
}
public string GetStringFromInt()
{
return _repository.GetInt().ToString();
}
}
Test
[Fact]
public void Test()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var repositoryMock = fixture.Create<Mock<IRepository>>();
var service = fixture.Create<Service>();
repositoryMock.Setup(x => x.GetInt()).Returns(1);
var act = service.GetStringFromInt();
Assert.Equal("1", act);
}
As you see value by default in Repository is 999 and I am expecting 1 from repositoryMock but result is "999" instead of "1".
Ow I have understood my problem. When I declare parameters with auto moq testing service must be AFTER all mocked repositories
Test
[Theory, AutoMoqData]
public void Test([Frozen] Mock<IRepository> repositoryMock, Service service)
{
...
}
Attribute
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute() : base(GetDefaultFixture)
{
}
private static IFixture GetDefaultFixture()
{
return new Fixture().Customize(new AutoMoqCustomization());
}
}
You should freeze your mock first. When you call Create on AutoFixture, it will create you a new instance every time. Try the following in the modified code (where you are using an interface of the type in your constructor).
public class ServiceTests
{
private readonly IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
public ServiceTests()
{
fixture.Register<IService>(() => fixture.Create<Service>());
}
[Fact]
public void Test()
{
// Arrange
var repositoryMock = fixture.Freeze<Mock<IRepository>>();
repositoryMock.Setup(x => x.GetInt()).Returns(1);
var service = fixture.Create<IService>();
// Act
var act = service.GetStringFromInt();
// Verify
Assert.Equal("1", act);
}
}
To check that you have set up autofixture correctly, you can try the following in the unit test in future.
var repo1 = fixture.Create<IRepository>();
var repo2 = fixture.Create<IRepository>();
Assert.Equal(repo1.GetHashCode(), repo2.GetHashCode());
If the above fails, that indicates that you have not frozen a type. These lines of code have saved me so much head scratching in the past...
You are doing DI wrong, you are not injecting Repository into Your serice.
Try like this.
public class Repository : IRepository
{
public int GetInt()
{
return 999;
}
}
public class Service : IService
{
IRepository Repository;
public Service(IRepository repository)
{
this.Repository = repository;
}
public string GetStringFromInt()
{
return Repository.GetInt().ToString();
}
}
Now when you mock IRepository, you can add it to Service.
You are using a new Repository() in constructor, so you are using that implementation
I an getting the below issue when running the Unit Test project.
Unable to get Default Constructor For class ********
[TestClass]
public class PersonRegistration
{
private ILoggingService _loggingService;
private IUserManager _userManager;
public PersonRegistration(IUserManager userManager, ILoggingService loggingService)
{
this._userManager = userManager;
this._loggingService = loggingService;
}
[TestMethod]
public void TestMethod1()
{
RegisterBindingModel model = new RegisterBindingModel();
AccountController ac = new AccountController(_userManager, _loggingService);
model.UserName = "test123#gmail.com";
var result = ac.Register(model);
Assert.AreEqual("User Registered Successfully", result);
}
How to fix that. Some answers says that to use a parameter less constructor. But here I need params.
RegisterBindingModel()
public class RegisterBindingModel
{
public RegisterBindingModel();
[Display(Name = "User name")]
[Required]
public string UserName { get; set; }
}
Issue
I've just tested this in my unit tests.
Add
public PersonRegistration()
{
}
And it should run fine.
There is no need for constructors on your unit test classses. If you are using a mocking framework like Moq then I use a factory to return the dependent moqs for the classes I'm testing.
public ILoggingService ReturnMockLoggingService()
{
var mockService = new Mock<ILoggingService>();
return mockService.Object;
}
Then in the test fixture.
[TestMethod]
public void TestMethod1()
{
RegisterBindingModel model = new RegisterBindingModel();
var logService = MockFactory.ReturnMockLoggingService();
var userService = MockFactory.ReturnMockUserService();
AccountController ac = new AccountController(userService, logService);
model.UserName = "test123#gmail.com";
var result = ac.Register(model);
Assert.AreEqual("User Registered Successfully", result);
}
if you're not using mocks then simply instance the user and log service in the test or create a SetUp.
[ClassInitialize]
public void SetUp()
{
_loggingService = new LoggingService();
_userManager = new UserManager();
}
Hope that helps.
You should use a mocking framework like Moq.
Example:
[TestClass]
public class PersonRegistration
{
[TestMethod]
public void TestMethod()
{
RegisterBindingModel model = new RegisterBindingModel();
var mockService = new Mock<ILoggingService>();//Mock
//Do something as per your requirement
//var reg= new List<RegisterBindingModel >(); // provide some sample list
//mockService .Setup(r => r.GetAll=()).Return(reg);
var mockManager = new Mock<IUserManager>();//Mock
//Do something as per your requirement
//var user= new List<User>(); // provide some sample list
//mockManager .Setup(r => r.GetAll=()).Return(user);
AccountController ac = new AccountController(mockManager.Object, mockService.Object);
model.UserName = "test123#gmail.com";
var result = ac.Register(model);
Assert.AreEqual("User Registered Successfully", result);
}
}
You can get help form this and this link.
I am doing a simple unit test where when creating a Course, the Title field cannot be empty. I am having to test it with a service class that has Dependency Injection with UnitOfWork. When I debug my test, I am getting an Exception error of Can not instantiate proxy of class: ContosoUniversity.Models.CourseRepository I looked into the error, but am not able to understand how to fix the issue and the Assert statement?
Error Message Display Image
CourseRepository
public class CourseRepository : GenericRepository<Course>
{
public CourseRepository(SchoolContext context)
: base(context)
{
}
UnitOfWork
public class UnitOfWork : IDisposable, IUnitOfWork
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
private CourseRepository courseRepository;
public CourseRepository CourseRepository
{
get
{
if (this.courseRepository == null)
{
this.courseRepository = new CourseRepository(context);
}
return courseRepository;
}
}
public virtual CourseRepository GetCourseRepository()
{
if (this.courseRepository == null)
{
this.courseRepository = new CourseRepository(context);
}
return courseRepository;
}
CourseService
public class CourseService : ICourseService
{
private IUnitOfWork unitOfWork;
public CourseService (IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void Create(Course course)
{
unitOfWork.GetCourseRepository().Insert(course);
unitOfWork.Save();
}
public Course GetCourseByID(int id)
{
return unitOfWork.GetCourseRepository().GetByID(id);
}
TestMethod
[TestMethod]
public void TestMethod1()
{
var course = new Course
{
CourseID = 2210,
Title = string.Empty,
Credits = 3,
DepartmentID = 1
};
Mock<CourseRepository> mockRepo = new Mock<CourseRepository>();
mockRepo.Setup(m => m.GetByID(course.CourseID)).Returns(course);
var mockUnit = new Mock<IUnitOfWork>();
mockUnit.Setup(x => x.GetCourseRepository()).Returns(mockRepo.Object);
var myService = new CourseService(mockUnit.Object);
myService.Create(course);
//var error = _modelState["Title"].Errors[0];
//Assert.AreEqual("The Title field is required.", error.ErrorMessage);
//mockRepo.Setup(x => x.Insert(course));
}
The error says that the CourseRepository can not be initialized because it does not have parameter less constructor. Mocking framework looks for parameter less constructor first to create mock object.
If your class does not have parameterless constructor then you need to pass those parameters when you create Mock. In your case mock of CourseRepository would be created as following.
var repositoryMock = new Mock<CourseRepository>(null);
Instead of null, you can pass mock objects of the constructor parameters also.
Just use the interface when mocking.
Mock<ICourseRepository> mockRepo = new Mock<ICourseRepository>();
mockRepo.Setup(m => m.GetByID(course.CourseID)).Returns(course);
Alternatively, if your class has an internal parameterless constructor, you need to add the InternalsVisibleTo attribute to assembly.
In case of Moq, add this:
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Or this, if you need an strong key
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
In my case, adding the [Frozen] attribute to my mock helped solve this problem.
I was also having the "cannot instantiate proxy of class error", but in my case, I was doing something like this:
[Theory, AutoMoqDate]
public async void Should_DoThis_When_ThatHappens(
Fixture fixture,
Mock<TroublesomeClass> troublesomeObject
){
var someResult = SomeObject();
troublesomeObject.Setup(o => o.SomeMethodAsync().ReturnsAsync(someResult);
// Code bellow is irrelevant...
}
For me, troublesomeObject's method was called in my suite's method, and when it got to SomeMethodAsync() is when the exception occurred.
When I added the [Frozen] tag before the troublesome object, the issue subsided.
Here's a sample of one of my unit test classes (pared down to the basics). In the controller, when the Index() action method is invoked, a call to GetByID(1234) always results in a newed up instance of a Ticket object. The object exists, but all of its properties are null, even though I've set them in my fake object. Any ideas as to why?
I'm using Moq.
Unit test
[TestClass]
public class TicketControllerTests : ControllerTestBase
{
protected Mock<ITicketRepository> MockTicketRepository = new Mock<ITicketRepository>();
[TestMethod]
public void IndexActionModelIsTypeOfTicketModel()
{
//ARRANGE
Mock<HttpContextBase> context = FakeHttpContext();
context.Setup(ctx => ctx.Session[SessionKeys.TokenData.ToString()]).Returns(Constants.TOKENDATA_SUBMITTER);
MockTicketRepository.Setup(x => x.GetById(It.IsAny<int>())).Returns(Constants.CLIENT_TICKET);
//ACT
var result = GetController(context.Object).Index(Constants.TICKET_ID);
var model = ((ViewResult)result).Model;
//ASSERT
Assert.IsInstanceOfType(model, typeof(TicketModel), "ViewModel should have been an instance of TicketModel.");
}
private TicketController GetController(HttpContextBase context)
{
var controller = new TicketController(MockTicketRepository.Object);
controller.ControllerContext = GetControllerContext(context, controller);
return controller;
}
}
Constants.CLIENT_TICKET
public static Ticket CLIENT_TICKET
{
get
{
var ticket = new Ticket
{
CategoryID = 1,
CreatedByUserId = 4
};
ticket.Clients.Add(new Client { ShortName = "Test Client 1"});
ticket.Clients.Add(new Client { ShortName = "Test Client 2" });
ticket.User = new User {FirstName = "First", LastName = "Last"};
return ticket;
}
}
Controller
private readonly ITicketRepository _ticketRepository;
public TicketController(ITicketRepository ticketRepository)
{
_ticketRepository = ticketRepository;
}
public ActionResult Index(int id)
{
var ticket = _ticketRepository.GetById(id);
// etc...
}
Could you show the controller code under test? It could be related to how you have set up the mocked context but it's hard to tell without seeing the controller code.
Also, if you add MockBehavior.Strict when you create the mock, it will bomb out if the invocation doesn't have a corresponding expectation:
protected Mock<ITicketRepository> MockTicketRepository = new Mock<ITicketRepository>(MockBehavior.Strict);
UPDATE
I've tried to strip everything back so that the test is as simple as possible to try and isolate the issue. Here's what I have come up with:
[TestClass]
public class TicketControllerTests : ControllerTestBase
{
protected Mock<ITicketRepository> MockTicketRepository;
[TestMethod]
public void IndexActionModelIsTypeOfTicketModel()
{
//ARRANGE
MockTicketRepository = new Mock<ITicketRepository>(MockBehavior.Strict);
MockTicketRepository.Setup(x => x.GetById(Constants.TICKET_ID)).Returns(Constants.CLIENT_TICKET);
var controller = new TicketController(MockTicketRepository.Object);
//ACT - try to keep ACT as lean as possible, ideally just the method call you're testing
var result = controller.Index(Constants.TICKET_ID);
//ASSERT
var model = ((ViewResult)result).ViewData.Model;
Assert.That(model, Is.InstanceOfType<TicketModel>(), "ViewModel should have been an instance of TicketModel.")
}
}