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
}
Related
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.
I am trying to run a Unit Test using NUnit and have therefore followed a tutorial, which states the following:
[TestFixture]
public class TestFootballplayerController
{
[Test]
public void FootBallPlayer_CheckingIfControllerReturnsCorrectView_MustReturnTrue()
{
string expected = "CreatePlayer";
FootballplayerController controller = new FootballPlayerController();
var result = controller.CreateIngredient() as ViewResult;
Assert.AreEqual(expected, result.ViewName);
}
}
The tutorial assumes I have a empty default constructor, but my constructor contains a parameter with my DBContext as follows:
public class FootballplayerController : Controller
{
private readonly FootballContext _context;
public FootballplayerController(FootballContext context)
{
_context = context;
}
public IActionResult CreatePlayer()
{
return View();
}
}
Visual Studio suggests that I create an empty constructor, but in that way I think I will just test something, that shouldn't be tested, instead of the correct constructor with the parameter.
If the answer is obvious, then I must say, I am new to unit testing, and can't work a way around this. Do I have to fake a parameter?
In this case, you can just mock this class using e.g MoQ framework
[Test]
public void FootBallPlayer_CheckingIfControllerReturnsCorrectView_MustReturnTrue()
{
string expected = "CreatePlayer";
var mock = new Mock<FootballContext>();
FootballplayerController controller = new FootballPlayerController(mock.Object);
var result = controller.CreateIngredient() as ViewResult;
Assert.AreEqual(expected, result.ViewName);
}
but you must remember that now is just empty class in this test. You can create better mock, by mocking all your DbSets, and make them IQueryable.
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 have a project created using Asp.Net Core, but I have a problem with unit testing one part of my controller's action, I use xUnit.net(2.2.0-beta2-build3300) for testing and Moq(4.6.25-alpha) for mocking, and FluentAssertions(4.13.0) and GenFu(1.1.1) to help me with my tests, I have a Unit of Work class (note that I cut it down to what's relevant to my question):
public class UnitOfWork : IUnitOfWork
{
private readonly WebForDbContext _context;
public UnitOfWork(WebForDbContext context)
{
_context = context;
}
private IContactRepository _contactRepository;
public IContactRepository ContactRepository
{
get
{
if (this._contactRepository == null)
{
this._contactRepository = new ContactRepository(_context);
}
return _contactRepository;
}
}
}
In my ContactRepository I have:
public class ContactRepository:IContactRepository
{
private WebForDbContext _context;
public ContactRepository(WebForDbContext context)
{
_context = context;
}
public Task<int> AddNewContactAsync(Contact contact)
{
_context.Contacts.Add(contact);
return _context.SaveChangesAsync();
}
}
I inject the Unit of Work to my controller, my action:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(ContactViewModel contactViewModel)
{
var contactWioutJavascript = _webForMapper.ContactViewModelToContact(contactViewModel);
int addContactResultWioutJavascript = await _uw.ContactRepository.AddNewContactAsync(contactWioutJavascript);
if (addContactResultWioutJavascript > 0)
{
return View("Success");
}
}
What I want to do is to stub my AddNewContactAsync method to return an integer bigger than 0 (10 in this case), to inter the if clause, and test to see if the correct view is returned, my test class:
public class ContactControllerTests
{
private Mock<IUnitOfWork> _uw;
private Mock<IWebForMapper> _webForMapper;
public ContactControllerTests()
{
_uw = new Mock<IUnitOfWork>();
_webForMapper = new Mock<IWebForMapper>();
}
[Fact]
public async Task Create_SouldReturnSuccessView_IfNewContactAdded()
{
var contactViewModel = A.New<ContactViewModel>();
_webForMapper.Setup(s => s.ContactViewModelToContact(contactViewModel)).Returns(A.New<Contact>());
_uw.Setup(u => u.ContactRepository.AddNewContactAsync(A.New<Contact>())).ReturnsAsync(10);
var sut = new ContactController(_uw.Object, _webForMapper.Object);
var result = (ViewResult)await sut.Create(contactViewModel);
result.ViewName.Should().Be("Success");
}
}
But the method AddNewContactAsync returns 0, and my test doesn't enter the if condition that leads to return View("Success"), I know that the problem doesn't have to do with ReturnAsync because I've used it with other async methods and it works, also _webForMapper is stubbed correctly and map the view model to my domain model and contactWioutJavascript is populated with value, but when I debug the test and reach the addContactResultWioutJavascript line, it returns 0, no matter what I do.
The things I did, but didn't work:
I mocked the ContactRepository, and tried to stub that instead:
_contactRepository.Setup(c => c.AddNewContactAsync(A.New<Contact>())).ReturnsAsync(10);
_uw.SetupGet<IContactRepository>(u => u.ContactRepository).Returns(_contactRepository.Object);
I also found other questions:
Moq Unit of Work
how to moq simple add function that uses Unit of Work and Repository Pattern
Mocking UnitOfWork with Moq and EF 4.1
But none of them helped, I'd appreciate any help.
You are almost there. Two things:
You do need to setup the ContactRepository property as Moq doesn't support "chaining" of setups.
Also, you need to use It.IsAny<>() instead of A.New<>():
_contactRepository.Setup(c => c.AddNewContactAsync(It.IsAny<Contact>())).ReturnsAsync(10);
This says "match any Contact that is passed in". When you used A.New<>(), you were saying "match the Contact instance that I just created with A.New<>(). In effect, that will never match anything since you didn't save or use the return value of A.New<>().
Using C# I'm trying to unit test controller actions and time how long it takes for them to return. I'm using the unit testing framework built into VS2012 Ultimate.
Unfortunately I'm also trying to wrap my head around TestContext and how to use it..
Some example code (my controller action):
[HttpPost]
public JsonResult GetUserListFromWebService()
{
JsonResult jsonResult = new JsonResult();
WebService svc = new WebService();
jsonResult.Data = svc.GetUserList(User.Identity.Name);
return jsonResult;
}
When I try to unit test this, User.Identity.Name is null so it throws an exception. My current unit test code looks like:
[TestClass]
public class ControllerAndRepositoryActionTests {
public TestContext testContext { get; set; }
private static Repository _repository;
private username = "domain\\foobar";
private static bool active = true;
[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
_repository = new WebServiceRepository();
}
#region Controller method tests
[TestMethod]
public void GetUserListReturnsData()
{
Controller controller = new Controller();
var result = controller.GetUserListFromWebService();
Assert.IsNotNull(result.Data);
}
#endregion
#region service repository calls - with timing
[TestMethod]
public void GetUserListTimed()
{
testContext.BeginTimer("Overall");
var results = _repository.GetUserList(username, active);
foreach (var result in results)
{
Console.WriteLine(result.UserID);
Console.WriteLine(result.UserName);
}
testContext.EndTimer("Overall");
}
#endregion
}
Can I use TestContext to set the User.Identity that will be eventually used in the GetUserListFromWebService call?
If I can, what is the accepted way to assign TestContext. When I get it as a param in MyClassInitialize do I set my member variable, or am I supposed to pass it as a param to the TestMethods in some way?
Am I completely missing the point and should I be using some other mocking framework?
To make this test to work, I should change the signature of your class. Because you can not make a stub or a mock of your class Webservice, because you are creating it in the method.
class YourClass
{
private readeonly WebService _ws;
public YourClass(WebService ws)
{
_ws=ws;
}
[HttpPost]
public JsonResult GetUserListFromWebService()
{
JsonResult jsonResult = new JsonResult();
jsonResult.Data = _ws.GetUserList(User.Identity.Name);
return jsonResult;
}
}
Now you can in your test easily mock the class WebService with Moq or other frameworks. To make it eaven easier you shoul create an interface to your class WebService that implements the method GetUserList();
And to mock the User.Identy
public SomeController CreateControllerForUser(string userName)
{
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
var controller = new SomeController();
controller.ControllerContext = mock.Object;
return controller;
}
Or read this blog post http://weblogs.asp.net/rashid/