I have a web api and I am exposing a endpoint like so:
api/Holiday?name={name}
This is the controller get method for the web api:
public IQueryable<Holiday> GetHolidayByName(string name)
{
return db.Holiday.Where(n => string.Equals(n.Name, name));
}
How can I write a unit/integration test for this that checks the names are equal? I can check the result is not null however bit confused how I can check the names are equal:
[TestMethod]
public void GetHoliday_GetHolidayByName()
{
// Arrange
HolidaysController controller = new HolidaysController();
// Act
IQueryable<Holiday> actionResult = controller.GetHolidayByName("Spain");
//Assert
Assert.IsNotNull(actionResult);
//any attempt to check names are equal results in a fail
//For instance this fails
var result = controller.GetHolidayByName("Spain") as OkNegotiatedContentResult<Holiday>;
Assert.AreEqual("Spain", result.Content.Name);
}
The test would look like this where you can use linq to verify that all the result returned satisfy your criteria.
[TestMethod]
public void GetHoliday_GetHolidayByName()
{
// Arrange
string name = "Spain";
HolidaysController controller = new HolidaysController();
// Act
IQueryable<Holiday> actionResult = controller.GetHolidayByName(name);
//Assert
Assert.IsNotNull(actionResult);
Assert.IsTrue(actionResult.All(n => string.Equals(n.Name, name));
}
The assumption here is that the db will provide you with the test data you want. Otherwise you will have to make some design changes to allow for providing mocked/fake data.
If you are connecting to an actual database then this is more an integration test rather than a unit test.
public interface IDbRepository
{
IQueryable<Holiday> GetHolidayByName(string name)
}
public class DbRepository : IDbRepository
{
public IQueryable<Holiday> GetHolidayByName(string name)
{
return db.Holiday.Where(n => string.Equals(n.Name, name));
}
}
private IDbRepository _dbRepository;//initialize, preferably through construtor
public IQueryable<Holiday> GetHolidayByName(string name)
{
return _dbRepository.GetHolidayByName(name)
}
First of all, I think that you should be testing db results but objects. Mock your method to give you "Holiday" Items, then override the "equals" method on the object, or just comparte the properties you need to check
Related
I am working in an ASP.net MVC 5 application. I would like to Unit Test my controller action which looks like this
public ActionResult Search()
{
var vm = SetupSearchViewModel();
return View(vm);
}
All the hard work is done by the SetupSearchViewModel() method, which itself is an orchestrator calling many different other methods, one of which is this
private string ExtractJsonFile(string filename)
{
var filePath = HttpContext.Server.MapPath(filename);
var json = System.IO.File.ReadAllText(filePath);
return json;
}
I plan on doing many Unit Tests on this particular action, but I'm starting with a very simple Unit Test which checks that the correct type of ActionResult is returned
[Test]
public void Search_Get_ReturnsViewResult()
{
// arrange
var performanceController = PerformanceControllerInstance;
// act
var result = performanceController.Search();
//assert
Assert.IsNotNull(result as ViewResult);
}
The test is failing because of the ExtractJsonFile method. It uses HttpContext and that is null. I am using Rhino Mocks to do the mocking of the various classes.
What would be the best way to Unit Test this? Darin in this thread suggest we avoid HttpContext.Current if we want our code Unit Tested.
By the way I tried mocking the HttpContext and made it not null, but then the Server is null, I can go ahead and mock that too I suppose (I don't know how yet), but is there no better way? I've no problem doing major refactoring if needed.
HttpContext.Server.MapPath would require an underlying virtual directory provider which would not exist during the unit test. Abstract the path mapping behind a service that you can mock to make the code testable.
public interface IPathProvider {
string MapPath(string path);
}
In the implementation of the concrete service you can make your call to map the path and retrieve the file.
public class ServerPathProvider: IPathProvider {
public string MapPath(string path) {
return HttpContext.Current.Server.MapPath(path);
}
}
you would inject the abstraction into your controller or where needed and used
public MyController : Controller {
public MyController(IPathProvider pathProvider) {
this.pathProvider = pathProvider;
}
//...other code removed for brevity
private string ExtractJsonFile(string filename) {
var filePath = pathProvider.MapPath(filename);
var json = System.IO.File.ReadAllText(filePath);
return json;
}
}
Using your mocking framework of choice you can then mock the provider
[Test]
public void Search_Get_ReturnsViewResult() {
// arrange
IPathProvider mockedPathProvider = //...insert your mock/fake/stub here
var performanceController = PerformanceControllerInstance(mockedPathProvider);
// act
var result = performanceController.Search();
//assert
Assert.IsNotNull(result as ViewResult);
}
and not be coupled to HttpContext
You could even go further and refactor the entire ExtractJsonFile(string filename) into its own service to get around being tied to disk as well.
public interface IJsonProvider {
string ExtractJsonFile(string filename);
}
This service is now flexible enough to get the file from other sources like web service if needed.
There is a method in my controller that returns attribute data from the current executing assembly into a partial view.
In this example, I'm merely pulling the Title, but I need to do more with it.
Controller:
var title = "";
var asm = Assembly.GetExecutingAssembly();
var attrs = asm.GetCustomAttributes(typeof(AssemblyTitleAttribute));
var titleAttr = (AssemblyTitleAttribute)attributes[0];
title = titleAttr.Title;
return PartialView("_Build", title);
When writing the unit test in Moq, I need to find a way to inject the Assembly attributes into a mock so that I can verify that the correct attributes are being generated when I run the controller test, and then do x or y with my asserts.
UnitTest:
//Arrange
//The magic I need to happen.
//Act
var controller = GetController();
var result = controller.MyMethod() as PartialViewResult;
var title = result.Model;
//Assert
Assert.AreEqual("Title", title); //currently static, need to verify against a mock
I know this is an extremely simple set of code, but I just need proof of concept at this point.
Is there a good way to create a fake Assembly?
Do I need to use System.Reflection.Emit?
You could create a virtual method e.g. GetCustomAttributes which provides the attributes for given type. Then in your test preject a testable class would derive from the controller class and override this method.
Home Controller:
private IDependency _someDependency;
public HomeController(IDependency someDependency)
{
_someDependency = someDependency;
}
public ActionResult MyMethod()
{
var title = "";
var version = "";
IEnumerable<Attribute> attributes = GetCustomAttributes(typeof(AssemblyVersionAttribute)).ToList();
AssemblyVersionAttribute verAttr = attributes.OfType<AssemblyVersionAttribute>().FirstOrDefault();
if (verAttr != null) version = verAttr.Version;
attributes = GetCustomAttributes(typeof(AssemblyTitleAttribute)).ToList();
AssemblyTitleAttribute titleAttr = attributes.OfType<AssemblyTitleAttribute>().FirstOrDefault();
if (titleAttr != null) title = titleAttr.Title;
return PartialView("_Build", title + version);
}
public virtual IEnumerable<Attribute> GetCustomAttributes(Type attributeType)
{
var asm = Assembly.GetExecutingAssembly();
var attrs = asm.GetCustomAttributes(attributeType);
return attrs;
}
Test:
[TestClass]
public class MyMethodTest
{
[TestMethod]
public void MyMethod_WhenCalled_PartialViewIsReturned()
{
// Arrange
// The magic I need to happen.
Mock<IDependency> dependencyStub = new Mock<IDependency>();
// dependencyStub.Setup(...).Returns(...);
var controller = new TestableHomeController(dependencyStub.Object)
{
UseFakeAttributes = true
};
// Act
var result = controller.MyMethod() as PartialViewResult;
// Assert
var model = result.Model;
Assert.AreEqual("MyFakeTitle1.0.0.0", model); // currently static, need to verify against a mock
}
private class TestableHomeController : HomeController
{
public bool UseFakeAttributes { get; set; }
public TestableHomeController(IDependency someDependency)
:base(someDependency)
{ }
public override IEnumerable<Attribute> GetCustomAttributes(Type attributeType)
{
return UseFakeAttributes
? new List<Attribute>
{
new AssemblyTitleAttribute("MyFakeTitle"),
new AssemblyVersionAttribute("1.0.0.0"),
new AssemblyDescriptionAttribute("Assembly fake description")
// next attributes ...
}.Where(a => a.GetType() == attributeType)
: base.GetCustomAttributes(attributeType);
}
}
}
Since this is static type information, you only need to evaluate it once per build. Consider populating a static collection (e.g. a dictionary) with this information at application start. At that point you can inject your dictionary into the controller, or you can modify your configuration to access the dictionary and inject only the values you need. In fact, provided this doesn't get out of control, it might be best to just have named string instances like "build" or "title" without even having to house them in a collection.
I wouldn't mess with the hassle of trying to get unit tests around parsing an assembly attribute unless the logic can be contained in a static method that your unit tests call directly. From a web app perspective, it's best to leave this type of stuff out of the controller; the bootstrapper layer is a much more appropriate location.
I have the only the following input data: the interface and the class. I don't have a class which implements the interface, neither any data about the client, his id and the other data. Only the following:
public interface IService
{
double GetData(int clientId);
}
public class ClientInfo
{
private int _clientId;
private IService _svc;
public double MoneySun;
public ClientInfo(int clientId, IService svc)
{
_clientId = clientId;
_svc = svc;
}
public void UpdateMoney()
{
MoneySun = _svc.GetData(_clientId);
}
}
And I need to write an Unit test for UpdateMoney method (taking into the account that I have only the info published above)
I wrote the following test and would like to consult whether it's correct or not?
[Test]
public void GetData()
{
Mock<IService> moqSvc = new Mock<IService>();
var сInfo = new ClientInfo(1, moqSvc.Object);
сInfo.UpdateMoney();
Assert.Greater(сInfo.MoneySun, -1);
}
And also, doing Assert I only guess that it must be grater than -1 so I'm not completely sure if this is correct. Also I only presume that there is a clientId =1
Since you are testing a service facade / proxy, mocking the service interface will allow you to determine if the interaction with the mocked interface was correct (unit tests on the other end of the wire on the actual service will need to be done to ensure that the correct transaction was done to the client).
You can also test that the state of the sut (ClientInfo) is consistent before and after the call:
[Test]
public void GetData()
{
var moqSvc = new Mock<IService>();
// Provide some fake data to ensure that the SUT uses the return value correctly
moqSvc.Setup(x => x.GetData(It.IsAny(int))).Returns(123.45);
var сInfo = new ClientInfo(1, moqSvc.Object);
// Ensure correct initial state
Assert.AreEqual(0, cInfo.MoneySun)
сInfo.UpdateMoney();
// Ensure correct final state
Assert.AreEqual(123.45, cInfo.MoneySun)
// Ensure correct interaction with the service
moqSvc.Verify(x => x.GetData(1), Times.Once);
moqSvc.Verify(x => x.GetData(It.IsAny<int>(i => i != 1)), Times.Never);
}
how can I write a unit test to test that asking for an interface does provide an implementation? I'm using NUnit together with StructureMap
Maybe something like this based on examples in the code? The problem I have is that I don't know how to setup the test.
Code snippet
[Test]
public void TestCustomerRegistration()
{
var res = ObjectFactory.GetInstance<ICustomer>();
Assert.IsNotNull(res, "Cannot get an Customer");
}
This is already present in the code
Not sure if I have to use a similar thing for my ICustomer test? Not sure what this is.
[TestFixtureSetUp]
public void SetUp()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<InfrastructureRegistry>();
x.AddRegistry<RepositoryRegistry>();
});
var container = ObjectFactory.Container;
IDependencyResolver resolver = new SmDependencyResolver(container);
ObjectFactory.Configure(x =>
{
x.For<IDependencyResolver>().Use(resolver);
});
}
Take the folloing MVC controller
I need to write a test that StructureMap provides 'Customer' when the _customer.GetById(id) is called. Hope this helps
private ICustomer _customer;
public MyController(ICustomer customer)
{
_customer = customer;
}
public ActionResult GetCustomer(int id)
{
var result = _customer.GetById(id); // I need to test that _customer works
}
Thanks,
If you are writing useless tests for checking some configuration of StructureMap (which is used for unit-tests, not for real running application), then it's easy to do! Use Assert.IsInstanceOf<T> to check exact type of returned object. It should be type which you are expecting StructureMap configured to return for customer interface:
[Test]
public void TestCustomerRegistration()
{
var customer = ObjectFactory.GetInstance<ICustomer>();
Assert.IsNotNull(customer, "Cannot get an Customer");
Assert.IsInstanceOf<SpecificCustomerType>(customer, "Wrong customer type");
}
UPDATE you should test controller in isolation from other objects (otherwise you will not know source of failures) and your controller test should look like (Moq sample)
[Test]
public void ShouldReturnExistingCustomer()
{
// Arrange
int id = 42; // or random numer
var dto = // data which ICustomer should return
Mock<ICustomer> customerMock = new Mock<ICustomer>();
customerMock.Setup(c => c.GetById(id)).Returns(dto)
var controller = new MyController(customer.Object);
// Act
var result = controller.GetCustomer(id);
// Assert
customerMock.VerifyAll();
Assert.IsNotNull(result); // etc
}
This is a controller test and it verifies that controller works (and calls customer to get data). If you want to verify _customer works, then you should write customer tests.
So I'm writing tests for our MVC4 application and I'm testing Controller actions specifically. As I mention in the title, the test still hits the service (WCF) instead of returning test data. I have this controller:
public class FormController : Controller
{
public SurveyServiceClient Service { get; set; }
public SurveyDao Dao { get; set; }
public FormController(SurveyServiceClient service = null, SurveyDao dao = null)
{
this.Service = service ?? new SurveyServiceClient();
this.Dao = dao ?? new SurveyDao(Service);
}
//
// GET: /Form/
public ActionResult Index()
{
var formsList = new List<FormDataTransformContainer>();
Dao.GetForms().ForEach(form => formsList.Add(form.ToContainer()));
var model = new IndexViewModel(){forms = formsList};
return View("Index", model);
}
And it uses this DAO object:
public class SurveyDao
{
private readonly SurveyServiceClient _service;
private readonly string _authKey;
public SurveyDao(SurveyServiceClient serviceClient)
{
_service = serviceClient;
}
....
public FormContract[] GetForms()
{
var forms = _service.RetrieveAllForms();
return forms;
}
And this is my test using JustMock, the mock on GetForms() returns some test data in a helper class:
[TestClass]
public class FormControllerTest
{
private SurveyDao mockDao;
private SurveyServiceClient mockClient;
public FormControllerTest()
{
mockClient = Mock.Create<SurveyServiceClient>();
mockDao = Mock.Create<SurveyDao>(mockClient);
}
[TestMethod]
public void TestIndexAction()
{
//Arrange
var controller = new FormController(mockClient, mockDao);
Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper);
//Act
var result = controller.Index() as ViewResult;
//Assert
Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel));
}
}
My problem is that when I run the test, the Service is still being called. I've verified this using Fiddler as well as debugging the test and inspecting the value of "result" which is populated with our service's test data.
EDIT:
I've changed the test constructor to be a [TestInitialize] function, so the Test now looks like this:
[TestClass]
public class FormControllerTest
{
private SurveyDao mockDao;
private SurveyServiceClient mockClient;
[TestInitialize]
public void Initialize()
{
mockClient = Mock.Create<SurveyServiceClient>();
mockDao = Mock.Create<SurveyDao>(Behavior.Strict);
}
[TestMethod]
public void TestIndexAction()
{
//Arrange
var controller = new FormController(mockClient, mockDao);
Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper);
//Act
var result = controller.Index() as ViewResult;
//Assert
Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel));
}
}
Please verify that you are using the correct assembly for JustMock. There are a few different ones (VisualBasic, Silverlight, JustMock). The JustMock one is the one you should be including in your project.
Failure to include the correct one will cause the behavior that you are describing (method not being properly stubbed).
The JustMock manual explains (highlights by me):
By default Telerik JustMock uses loose mocks and allows you to call
any method on a given type. No matter whether the method call is
arranged or not you are able to call it.
You can control this behavior when calling the Create() method of you Mock:
var foo = Mock.Create<IFoo>(Behavior.Strict);
There you can specify what the mock object should do if you have not explicitly implemented a certain method. In your case (I think it is the default behavior) the mock indeed calls the original method on the object that you want to mock.
You have the following choices in the Behavior Enumeration enumeration:
Loose: Specifies that by default mock calls will behave like a stub, unless explicitly setup.
RecursiveLoose: Specifies that by default mock calls will return mock objects, unless explicitly setup.
Strict: Specifies that any calls made on the mock will throw an exception if not explictly set.
CallOriginal: Specifies that by default all calls made on mock will invoke its corresponding original member unless some expecations are set.