Reputation: 1992
Caveat: I'm brand spanking new to Moq, Unit Testing with Moq, and TDD, generally.
I have a controller with three dependencies. Here is the Constructor (etc) to the SomethingController:
public class SomethingController : Controller
{
private readonly ILogger<SomethingController> _logger;
private readonly ISomethingRepository _something;
private readonly IExceptionSvc _ex;
public SomethingController(ILogger<SomethingController> logger,
ISomethingRepository something,
IExceptionSvc ex)
{
_logger = logger;
_something = something;
_ex = ex;
}
[HttpGet]
[AllowAnonymous]
public JsonResult GetStuff()
{
//intitialize list
var stuffs = new List<StuffViewModel>();
try
{
_logger.LogInformation("SomethingController: GetStuff() - Getting Stuff, sorted ascending.");
//get the stuffs
stuffs = _something.GetStuff();
_logger.LogInformation("Retrieved {0} Stuffs.", stuffs.Count);
}
catch (Exception ex)
{
_logger.LogError("Error in SomethingController: GetStuff()", ex);
return _ex.Http500ErrorReturn("GetStuff");
}
return Json(stuffs);
}
}
Now, here is the description of what each dependency is for:
ILogger: This is simply for logging, using Microsoft.Extensions.Logging via NLog.
ISomethingRepository: This does all the work (well...the impementation of it, really). It calls the database and gets things. There is a method called GetStuff(), which simply returns a list of Stuffs. This Repository has a dependency on the database, which is injected into the repo via the constructor.
IExceptionSvc: This is just a dumb little service that has a method that returns a 500 Error response for a JSON formatted return to the caller.
I want to test the GetStuff() action in the Controller, which will call the GetStuff() implementation in the Repository.
I currently have the following code stubbed in, in my test project:
public void GetStuff_Is_Awesome()
{
Mock<ILogger<SomethingController>> logger = new Mock<ILogger<SomethingController>>();
Mock<ISomethingRepository> something = new Mock<ISomethingRepository>();
Mock <IExceptionSvc> ex = new Mock<IExceptionSvc>();
SomethingController sc = new SomethingController(logger.Object, something.Object, ex.Object);
sc.GetStuff();
//...what now? What am I looking for? Am I going to see a list of stuffs here?
}
I just want to know what to expect? Am I testing whether a list of Stuffs was returned? How do I test that?
Here is the implementation of GetStuff() in the Repository (with the repo constructor for reference sake):
private readonly ApplicationDbContext _context;
private readonly ILogger<SomethingRepository> _logger;
public SomethingRepository(ApplicationDbContext context,
ILogger<SomethingRepository> logger)
{
_context = context;
_logger = logger;
}
public List<StuffViewModel> GetStuff()
{
List<StuffViewModel> stuffs = null;
stuffs = _context.Stuffs.OrderBy(b => b.Name).Select(b => new StuffViewModel
{
Id = b.Id,
Name = b.Name
}).ToList();
return stuffs;
}
Upvotes: 1
Views: 1100
Reputation: 38509
Think of it as Arrange, Act Assert
public void GetStuff_Is_Awesome()
{
//arrange
Mock<ILogger<SomethingController>> logger = new Mock<ILogger<SomethingController>>();
Mock<ISomethingRepository> something = new Mock<ISomethingRepository>();
Mock <IExceptionSvc> ex = new Mock<IExceptionSvc>();
SomethingController sc = new SomethingController(logger.Object, something.Object, ex.Object);
//act
sc.GetStuff();
//assert
}
So, you want to assert that something happened, or something was called.
Without knowing more about your domain, or the ISomethingRepository, you could Assert that the method was called:
something.Verify(m => m.MethodToCheckIfCalled());
Other options would be to setup the return values for MethodToCheckIfCalled
and assert the results etc...
Assuming a GetStuff
method on your controller that looks like:
public ActionResult GetStuff()
{
var data = _something.GetFromRepo();
return View(data);
}
I would do something like:
public void GetStuff_Is_Awesome() //please don't call it this
{
//arrange
Mock<ILogger<SomethingController>> logger = new Mock<ILogger<SomethingController>>();
Mock<ISomethingRepository> something = new Mock<ISomethingRepository>();
Mock <IExceptionSvc> ex = new Mock<IExceptionSvc>();
SomethingController sc = new SomethingController(logger.Object, something.Object, ex.Object);
//setup your something mock GetFromRepo method to return a List of StuffViewModel
something.Setup(m=> m.GetFromRepo())
.Returns(new List<StuffViewModel>(){Id = 1, Name = "Test"});
//act
var result = sc.GetStuff();
//assert
//safely cast result to ViewResult
var viewResult = result as ViewResult;
Assert.IsNotNull(viewResult);
Assert.IsNotNull(viewResult.Model);
// add additional checks on the Model.. loads of ways of doing this
var viewResultModel = viewResut.Model as List<StuffViewModel>;
Assert.AreEqual(1, viewResultModel.First().Id);
Assert.AreEqual("Test", viewResultModel.First().Name);
}
Upvotes: 4