I'm trying to test my controllers using xUnit but getting the following error during execution of Customer Controller:
"The following constructor parameters did not have matching fixture
data: CustomerController customerController"
Test Class
public class UnitTest1
{
CustomerController _customerController;
public UnitTest1(CustomerController customerController)
{
_customerController = customerController;
}
[Fact]
public void PostTestSuccessful()
{
Guid guid = Guid.NewGuid();
CustomerViewModel model = new CustomerViewModel()
{
Id = guid,
Name = "testName",
Email = "test email",
PhoneNumber = "test phone",
Address = "test address",
City = "test city",
Gender = "Male"
};
var actionResult = _customerController.Post(model);
Assert.NotNull(actionResult);
Assert.IsType<Task<IActionResult>>(actionResult);
Assert.True(actionResult.IsCompletedSuccessfully);
}
CustomerController Class
[Route("customers")]
public class CustomerController : ControllerBase
{
private readonly ILogger _logger;
private readonly ICustomerService _customerService;
public CustomerController(ILogger<CustomerController> logger,
ICustomerService customerService)
{
_logger = logger;
_customerService = customerService;
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] CustomerViewModel viewModel)
{
var customerToBeSaved = viewModel.Adapt<CustomerServiceModel>();
var customer = await _customerService.SaveAsync(customerToBeSaved);
var result = customer.Adapt<CustomerViewModel>();
return Ok(result);
}
What you are missing is the IClassFixture interface for the test class. This will fix the problem...
public class UnitTest1 : IClassFixture<CustomerController>
Just new up CustomerController in the constructor, if you don't want to use any mocking framework.
This article shows how to get xunit working with .Net Core ASP.Net really well. It actually replaces the startup so that your controllers run in the same process, and you can test them as if they were local.
https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests
It allows your standard .Net Dependency Injection to work as it normally does. Moreover it has the amazing benefit of not running as a server, and it fakes the whole startup process so that it runs in one single process and you can debug all the way through. This is also the way you should do it because Microsoft says so.
There's more help to be gleaned from the forum at the bottom of the article.
For the testing framework, you need the mocking library to inject a mock object through DI in your testing classes. You can use Nmock, Moq or any other mocking library to setup the constructor injection.
https://www.c-sharpcorner.com/uploadfile/john_charles/mocking-in-net-with-moq/
http://nmock.sourceforge.net/quickstart.html
Your Test Class Need to Inject ILogger and ICustomerService in Constructor
I Suggest you to Use Mock and Inject Controller Constructor Inputs in Test Class with Mocking
But Don't forget to Set Up the Mocked Objects or Interfaces
Learn More About Mock Here.....enter link description here
Related
this test always return null, and test always fail...but when i run the projet all works fine and return data normally, this project using RavenDB
Controller
[Route("api/[controller]")]
public class CategoryController : Controller
{
private readonly AppDbContext _context = new AppDbContext();
// GET: api/category
[HttpGet("{id}")]
public async Task<JsonResult> Get(string id)
{
using (IAsyncDocumentSession session = _context.SessionAsync){
var result = await session.LoadAsync<Category>(id);
return Json(result);
}
}
}
and using xUnit to testing
[Fact]
public async Task GetShouldReturnCategory()
{
// Arrange
var _categoryController = Substitute.For<CategoryController>();
var category = CreateCategory();
// Act
var result = await _categoryController.Get(category.Result.Id);
//Asserts here
}
Base on your question, system under test (SUT) is CategoryController. So, it doesn't make sense to mock CategoryController; instead, you want to mock AppDbContext.
If you want to unit test a controller, you should use ASP.NET Core's Dependency Inject, and inject its dependencies via constructor injection. In other words, you should not use new.
Normally, we inject interface instead of concrete class, so that we can easily mock it.
Your code is missing too many pieces, so I could only give you a directly. You want more detail you can look at this sample project at GitHub which uses NSubstitute and XUnit.
I'm creating a solution that contains two projects: the web project ant it's test project. I'm using Log4net for logging purposes, CastleWindsor for dependency injection and moq for the tests.
The problem I have is the configuration of the test. I want to test the HomeController that is Logging to a file, but when I run the test I don't want to Log, I think is absurd.
Is there a way to skip Logging in the test project?
The HomeController class:
public class HomeController : Controller
{
// this is Castle.Core.Logging.ILogger, not log4net.Core.ILogger
public ILogger Logger { get; set; }
private IRowan _rowan;
public HomeController(IRowan rowan)
{
_rowan = rowan;
}
public ActionResult Index()
{
//In the [tests] Logger fails
Logger.Debug("GET Request traced");
Logger.Error("Example of Error");
String test = _rowan.DoSomething();
ViewBag.Title = test;
return View();
}
}
}
It's test:
[TestClass]
public class HomeControllerTest
{
private static WindsorContainer _container;
[ClassInitialize()]
public static void InstallWindsor()
{
_container = new WindsorContainer();
// configure other classes
}
[ClassCleanup()]
public static void DisposeContainer()
{
_container.Dispose();
}
[TestMethod]
public void Index()
{
// Disponer
var mock = new Mock<IRowan>();
mock.Setup(m => m.DoSomething()).Returns("Home Page");
HomeController controller = new HomeController(mock.Object);
// Actuar
ViewResult result = controller.Index() as ViewResult;
// Declarar
Assert.IsNotNull(result);
Assert.AreEqual("Home Page", result.ViewBag.Title);
}
}
If the answer is no, which is the best way to implement log4net for testing?
PD: When I run the code, It works fine. When I run the test, Logger throws an exception because is null.
PD: I'm starting using the Microsoft Technology.
You could mock your Logger and set it on your controller like so:
Mock<ILogger> mockLogger = new Mock<ILogger>();
controller.Logger = mockLogger.Object;
Note that you shouldn't really need to use CastleWindsor in your tests. That's useful for controlling the lifecycle of objects in your application but in your tests you should be injecting things by hand. You are actually doing this in the example above. From the code you've posted you can remove the ClassInitialize and ClassCleanup functions and it will run the same.
You can use an other config for your test project.
Read more: https://logging.apache.org/log4net/release/manual/configuration.html
I am implementing nUnit Test case for one of my method called, UploadFile(), some thing like below
public void UploadFile(string siteId, string sitePageId)
{
int fileCount = HttpContext.Current.Request.Files.Count;
//Rest of code
}
so basically i am reading file using HttpContext.Current.Request.Files.
From UI it is working fine but when i am implementing nUnit test case for it, i am not able to mock HttpContext.Current.Request.Files. I googled about some of mocking tools but there also i didn't get anything related to mocking of HttpContext.Current.Request.Files. Please help me how to mock it or write test case for my method.
You could use dependency injection and then inject an instance of HttpContextBase into the class. Supposing you're using MVC:
public class MyController : Controller
{
HttpContextBase _context;
public MyController(HttpContextBase context)
{
_context = context
}
public void UploadFile(string siteId, string sitePageId)
{
int fileCount = _context.Request.Files.Count;
//Rest of code
}
}
Now you can instantiate the controller with a mock of HttpContextBase. This is how you would do it with Moq:
[Test]
public void File_upload_test()
{
var contextmock = new Mock<HttpContextBase>();
// Set up the mock here
var mycontroller = new MyController(contextmock.Object);
// test here
}
I am trying to use the fluent test helpers to test an AbstractRestfulFluentController
public class CustomerController : AbstractRestfulFluentController
{
private readonly IService<Customer> _customerService;
private readonly IService<CustomerAddress> _addressService;
public CustomerController(IService<Customer> customerService, IService<CustomerAddress> addressService)
{
//Assume we use these in other actions
_customerService = customerService;
_addressService = addressService;
}
public ActionResult Index()
{
return View();
}
}
As you can see I am injecting some services into the controller and resolving them using IOC. My problem is that all the examples I have found using the fluent test methods in mvccontrib don't work without a paramaterless controller.
public void SuccessfulIndex()
{
GivenController.As<CustomerController>()
.ShouldRenderItself(RestfulAction.Index)
.WhenCalling(x => x.Index());
}
I'm not sure what I need to do in order to be able to use IOC with the fluent test techniques in mvccontrib. I have found a few comments that it is possible but haven't found anything. What can I do in order to actually use IOC and fluent tests?
You could write a method which allows you to provide the instance of the controller:
public static class GivenController
{
public static ActionExpectations<T> As<T>(T controller) where T: Controller, new()
{
return new ActionExpectations<T> { MockController = controller };
}
}
And then in your unit test:
var controller = CreateMockedCustomerController();
GivenController
.As<CustomerController>(controller)
.ShouldRenderItself(RestfulAction.Index)
.WhenCalling(x => x.Index());
The requirement is that the controller should be a mock object which in my opinion is not a very clean approach (testing a mocked object). You could create it like this:
var controller = MockRepository
.GeneratePartialMock<CustomerController>(new object[] { dep1, dep2 });
Notice how dependencies are passed to the constructor.
Have you tried property injection instead of constructor injection?
http://ninject.codeplex.com/wikipage?title=Injection%20Patterns
I am currently having a weird ninject issue that I just posted about, but this should at least point you in the right direction...all the code is there for setting up the dependency injection.
https://stackoverflow.com/questions/3909452/unit-testing-asp-net-mvc-controllers-with-ninject
I’m relatively new to testing and MVC and came across a sticking point today. I’m attempting to test an action method that has a dependency on HttpContext.Current.Cache and wanted to know the best practice for achieving the “low coupling” to allow for easy testing. Here's what I've got so far...
public class CacheHandler : ICacheHandler
{
public IList<Section3ListItem> StateList
{
get { return (List<Section3ListItem>)HttpContext.Current.Cache["StateList"]; }
set { HttpContext.Current.Cache["StateList"] = value; }
}
...
I then access it like such... I'm using Castle for my IoC.
public class ProfileController : ControllerBase
{
private readonly ISection3Repository _repository;
private readonly ICacheHandler _cache;
public ProfileController(ISection3Repository repository, ICacheHandler cacheHandler)
{
_repository = repository;
_cache = cacheHandler;
}
[UserIdFilter]
public ActionResult PersonalInfo(Guid userId)
{
if (_cache.StateList == null)
_cache.StateList = _repository.GetLookupValues((int)ELookupKey.States).ToList();
...
Then in my unit tests I am able to mock up ICacheHandler.
Would this be considered a 'best practice' and does anyone have any suggestions for other approaches?
The recommended approach is to stub HttpContextBase. Its documentation states
When you perform unit testing, you
typically use a derived class to
implement members with customized
behavior that fulfills the scenario
you are testing.
This is mostly covered for TypeMock here.
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
httpContext.Stub(x=>x.Cache).Return(yourFakeCacheHere);
var controllerContext = new ControllerContext(httpContext, ....);
var controller = new HomeController();
controller.ControllerContext = controllerContext;
You are hiding a specific, hard-to-test API (HttpContext.Current) behind and interface and using Constructor Injection to inject the dependency into the consumer. That's more or less textbook DI (I would add Guard Clauses in the constructor, though).
If you create a new ASP.NET MVC project in Visual Studio, you will see that in the AccountController.cs file, a very similar thing is being done to hide the MembershipProvider.