How to unit test the controller? - asp.net

I have the controller in ASP.NET Mvc 6.
public class VendorManagementController : Controller
{
private readonly IVendorRespository _vendorRespository;
public VendorManagementController(IVendorRespository vendorRespository)
{
_vendorRespository = vendorRespository;
}
[Microsoft.AspNet.Mvc.HttpGet]
public dynamic GetVendorById(int pkey)
{
Vendor vendor = _vendorRespository.GetVendor(pkey);
return vendor;
}
// GET
// USing JqGrid
[Microsoft.AspNet.Mvc.HttpGet]
public dynamic GetVendors(string sidx, string sortOrder, int page, int rows, int pkey)
{
var vendors = _vendorRespository.GetAllVendors().AsQueryable();
var pageIndex = Convert.ToInt32(page) - 1;
var pageSize = rows;
var totalRecords = vendors.Count();
var totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
return something
}
// POST
[System.Web.Http.HttpPost]
public string PostVendor(Vendor item)
{
_vendorRespository.AddVendor(item);
}
The link provides an example to test the controller, but it uses HttpRequestMessage. It doesn't fit my case.
So if I want to test the return Vendors, how?
Say I have the method:
[Fact]
public void GetAllVendors_ShouldReturnAllVendors()
{
var testVendors = GetTestVendors();
var vendorRespository = new VendorRespository();
var controller = new VendorManagementController(vendorRespository);
}
The thing is
var vendors = _vendorRespository.GetAllVendors().AsQueryable();
from the databse, how to mock up it with my fake vendors?
EDIT:
The method returns dynamic type, I can't get the Count of the list.

Install a mocking framework such as Moq from nuget - https://www.nuget.org/packages/Moq/.
using Moq;
[Fact]
public void GetAllVendors_ShouldReturnAllVendors()
{
var testVendors = GetTestVendors();
var vendorRespository = new Mock<IVendorRepository>();
vendorRepository.Setup(m => m.GetAllVendors()).Returns(new List<Vendor> { new Vendor() }); // Guessing a bit on return types
var controller = new VendorManagementController(vendorRespository.Object);
var result = controller.GetVendors( ... )
// Assert you get 1 Vendor back, not sure what you're planning to return by "something". :-)
}
Other frameworks are available, NSubsititute, FakeItEasy

Related

Web API Typeless OData Service with OWIN self-hosting returns 406 Not Acceptable

I'm trying to set up a Web API Typeless OData Service with OWIN self-hosting... =)
But why not working? :~(
This is some code I have partially extracted from all kinds of examples out there...
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
appBuilder.UseWebApi(config);
}
}
public class Program
{
public static IEdmModel Model = GetEdmModel();
static void Main(string[] args)
{
using (WebApp.Start<Startup>("http://localhost:8080"))
{
Console.WriteLine("Running...");
Console.ReadLine();
}
}
public static IEdmModel GetEdmModel()
{
var model = new EdmModel();
// Create and add product entity type.
var product = new EdmEntityType("NS", "Product");
product.AddKeys(product.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
product.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
product.AddStructuralProperty("Price", EdmPrimitiveTypeKind.Double);
model.AddElement(product);
// Create and add category entity type.
var category = new EdmEntityType("NS", "Category");
category.AddKeys(category.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
category.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
model.AddElement(category);
// Set navigation from product to category.
var propertyInfo = new EdmNavigationPropertyInfo();
propertyInfo.Name = "Category";
propertyInfo.TargetMultiplicity = EdmMultiplicity.One;
propertyInfo.Target = category;
var productCategory = product.AddUnidirectionalNavigation(propertyInfo);
// Create and add entity container.
var container = new EdmEntityContainer("NS", "DefaultContainer");
model.AddElement(container);
// Create and add entity set for product and category.
var products = container.AddEntitySet("Products", product);
var categories = container.AddEntitySet("Categories", category);
products.AddNavigationTarget(productCategory, categories);
return model;
}
}
public class ProductsController : ODataController
{
private static readonly IQueryable<IEdmEntityObject> Products = Enumerable.Range(0, 10).Select(i =>
{
var productType = (IEdmEntityType)Program.Model.FindType("NS.Product");
var categoryType = (IEdmEntityTypeReference)productType.FindProperty("Category").Type;
var product = new EdmEntityObject(productType);
product.TrySetPropertyValue("Id", i);
product.TrySetPropertyValue("Name", "Product " + i);
product.TrySetPropertyValue("Price", i + 0.01);
var category = new EdmEntityObject(categoryType);
category.TrySetPropertyValue("Id", i % 5);
category.TrySetPropertyValue("Name", "Category " + (i % 5));
product.TrySetPropertyValue("Category", category);
return product;
}).AsQueryable();
public EdmEntityObjectCollection Get()
{
// Get Edm type from request.
var path = this.Request.GetODataPath();
var edmType = path.EdmType;
Contract.Assert(edmType.TypeKind == EdmTypeKind.Collection);
var collectionType = edmType as IEdmCollectionType;
var entityType = collectionType.ElementType.Definition as IEdmEntityType;
var model = Request.GetEdmModel();
var queryContext = new ODataQueryContext(model, entityType);
var queryOptions = new ODataQueryOptions(queryContext, Request);
// Apply the query option on the IQueryable here.
return new EdmEntityObjectCollection(new EdmCollectionTypeReference(collectionType, false), Products.ToList());
}
public IEdmEntityObject GetProduct(int key)
{
object id;
var product = Products.Single(p => HasId(p, key));
return product;
}
public IEdmEntityObject GetCategoryFromProduct(int key)
{
object id;
var product = Products.Single(p => HasId(p, key));
object category;
if (product.TryGetPropertyValue("Category", out category))
{
return (IEdmEntityObject)category;
}
return null;
}
public IEdmEntityObject Post(IEdmEntityObject entity)
{
// Get Edm type from request.
var path = Request.GetODataPath();
var edmType = path.EdmType;
Contract.Assert(edmType.TypeKind == EdmTypeKind.Collection);
var entityType = (edmType as IEdmCollectionType).ElementType.AsEntity();
// Do something with the entity object here.
return entity;
}
private bool HasId(IEdmEntityObject product, int key)
{
object id;
return product.TryGetPropertyValue("Id", out id) && (int)id == key;
}
}
The result I get is:
{StatusCode: 406, ReasonPhrase: 'Not Acceptable', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Date: Mon, 12 May 2014 18:08:25 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 0
}}
From running this:
var client = new HttpClient();
var response = client.GetAsync("http://localhost:8080/api/Products").Result;
If you are using OData V4, you need to make a change in your controller:
Old:
using System.Web.Http.OData;
New:
using System.Web.OData;

How to test a class with delegate in constructor using Moq

Can someone explain to me how to create an instance of this component in a Moq TestMethod? Here is the definition of the class. I need to test the ProcessAutomaticFillRequest method.
public class AutomaticDispenserComponent : IAutomaticDispenserComponent
{
private readonly Lazy<IMessageQueueComponent> _messageQueueComponent;
protected IMessageQueueComponent MessageQueueComponent { get { return _messageQueueComponent.Value; } }
public AutomaticDispenserComponent(Func<IMessageQueueComponent> messageQueueComponentFactory)
{
_messageQueueComponent = new Lazy<IMessageQueueComponent>(messageQueueComponentFactory);
}
public void ProcessAutomaticFillRequest(FillRequestParamDataContract fillRequestParam)
{
if (fillRequestParam.PrescriptionServiceUniqueId == Guid.Empty)
throw new InvalidOperationException("No prescription service was specified for processing fill request.");
if (fillRequestParam.Dispenser == null)
throw new InvalidOperationException("No dispenser was specified for processing fill request.");
var userContext = GlobalContext.CurrentUserContext;
var channel = string.Format(Channel.FillRequest, userContext.TenantId,
userContext.PharmacyUid, fillRequestParam.Dispenser.DeviceAgentUniqueId);
NotificationServer.Publish(channel, fillRequestParam);
}
Here is how I started my test, but I don't know how to create an instance of the component:
[TestMethod]
[ExpectedException(typeof (InvalidOperationException))]
public void FillRequestFailsWhenPrescriptionServiceUniqueIdIsEmpty()
{
// How do I create an instance of automatiqueDispenserComponent here
// since there is Func as constructor parameter?
var fillRequestParam = new FillRequestParamDataContract
{
PrescriptionServiceUniqueId = Guid.Empty
};
_automaticDispensercomponent.ProcessAutomaticFillRequest(fillRequestParam);
// ...
}
Updated the answer based on the comments below. You need to mock the Func parameter for the test.
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void FillRequestFailsWhenPrescriptionServiceUniqueIdIsEmpty()
{
var mockMsgQueueComponent = new Mock<Func<IMessageQueueComponent>>();
var _automaticDispensercomponent = new AutomaticDispenserComponent
(mockMsgQueueComponent.Object);
var fillRequestParam = new FillRequestParamDataContract
{
PrescriptionServiceUniqueId = Guid.Empty
};
_automaticDispensercomponent.ProcessAutomaticFillRequest(fillRequestParam);
}

How can i use engine object in my console application

"How can i use engine in my console application"
I shouldn't use the ITemplate-interface and Transform-Method.
I am using Tridion 2011
Could anyone please suggest me.
You can't. The Engine class is part of the TOM.NET and that API is explicitly reserved for use in:
Template Building Blocks
Event Handlers
For all other cases (such as console applications) you should use the Core Service.
There are many good questions (and articles on other web sites) already:
https://stackoverflow.com/search?q=%5Btridion%5D+core+service
http://www.google.com/#q=tridion+core+service
If you get stuck along the way, show us the relevant code+configuration you have and what error message your get (or at what step you are stuck) and we'll try to help from there.
From a console application you should use the Core Service. I wrote a small example using the Core Service to search for items in the content manager.
Console.WriteLine("FullTextQuery:");
var fullTextQuery = Console.ReadLine();
if (String.IsNullOrWhiteSpace(fullTextQuery) || fullTextQuery.Equals(":q", StringComparison.OrdinalIgnoreCase))
{
break;
}
Console.WriteLine("SearchIn IdRef:");
var searchInIdRef = Console.ReadLine();
var queryData = new SearchQueryData
{
FullTextQuery = fullTextQuery,
SearchIn = new LinkToIdentifiableObjectData
{
IdRef = searchInIdRef
}
};
var results = coreServiceClient.GetSearchResults(queryData);
results.ToList().ForEach(result => Console.WriteLine("{0} ({1})", result.Title, result.Id));
Add a reference to Tridion.ContentManager.CoreService.Client to your Visual Studio Project.
Code of the Core Service Client Provider:
public interface ICoreServiceProvider
{
CoreServiceClient GetCoreServiceClient();
}
public class CoreServiceDefaultProvider : ICoreServiceProvider
{
private CoreServiceClient _client;
public CoreServiceClient GetCoreServiceClient()
{
return _client ?? (_client = new CoreServiceClient());
}
}
And the client itself:
public class CoreServiceClient : IDisposable
{
public SessionAwareCoreServiceClient ProxyClient;
private const string DefaultEndpointName = "netTcp_2011";
public CoreServiceClient(string endPointName)
{
if(string.IsNullOrWhiteSpace(endPointName))
{
throw new ArgumentNullException("endPointName", "EndPointName is not specified.");
}
ProxyClient = new SessionAwareCoreServiceClient(endPointName);
}
public CoreServiceClient() : this(DefaultEndpointName) { }
public string GetApiVersionNumber()
{
return ProxyClient.GetApiVersion();
}
public IdentifiableObjectData[] GetSearchResults(SearchQueryData filter)
{
return ProxyClient.GetSearchResults(filter);
}
public IdentifiableObjectData Read(string id)
{
return ProxyClient.Read(id, new ReadOptions());
}
public ApplicationData ReadApplicationData(string subjectId, string applicationId)
{
return ProxyClient.ReadApplicationData(subjectId, applicationId);
}
public void Dispose()
{
if (ProxyClient.State == CommunicationState.Faulted)
{
ProxyClient.Abort();
}
else
{
ProxyClient.Close();
}
}
}
When you want to perform CRUD actions through the core service you can implement the following methods in the client:
public IdentifiableObjectData CreateItem(IdentifiableObjectData data)
{
data = ProxyClient.Create(data, new ReadOptions());
return data;
}
public IdentifiableObjectData UpdateItem(IdentifiableObjectData data)
{
data = ProxyClient.Update(data, new ReadOptions());
return data;
}
public IdentifiableObjectData ReadItem(string id)
{
return ProxyClient.Read(id, new ReadOptions());
}
To construct a data object of e.g. a Component you can implement a Component Builder class that implements a create method that does this for you:
public ComponentData Create(string folderUri, string title, string content)
{
var data = new ComponentData()
{
Id = "tcm:0-0-0",
Title = title,
Content = content,
LocationInfo = new LocationInfo()
};
data.LocationInfo.OrganizationalItem = new LinkToOrganizationalItemData
{
IdRef = folderUri
};
using (CoreServiceClient client = provider.GetCoreServiceClient())
{
data = (ComponentData)client.CreateItem(data);
}
return data;
}
Hope this gets you started.

TDD problem in ASP.NET MVC3 (with DI)

I am attempting to write some Tests for a small project of mine but they seem to fail (I am starting with 1 test 'Create_Class')
I use the repository pattern and use Constructor Dependency Injection:
public KlasController() {
db = ObjectContextPerHttpRequest.Context;
KlasRepo = new KlasRepository(db);
LesRepo = new LesRepository(db);
OpdrachtRepo = new OpdrachtRepository(db);
}
//dependency injection constructor
public KlasController(IKlasRepository KlasRepo, ILesRepository LesRepo,
IOpdrachtRepository OpdrachtRepo) {
this.KlasRepo = KlasRepo;
this.LesRepo = LesRepo;
this.OpdrachtRepo = OpdrachtRepo;
}
here is my TestClass with testinitializer (which runs before every test) and the first test
[TestClass()]
public class KlasControllerTest
{
private KlasController Controller;
private IOpdrachtRepository OpdrachtRepo;
//Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
OpdrachtRepo = new DummyOpdrachtRepository();
Controller = new KlasController(new DummyKlasRepository(),
new DummyLesRepository(), OpdrachtRepo);
Opdracht TestOpdracht = new Opdracht
{
OpdrachtID = 1,
VakID = 1,
StamNummer = "im1"
};
Vak TestVak = new Vak { VakID = 1, VakNaam = "FOOP" };
TestOpdracht.Vak = TestVak;
OpdrachtRepo.addOpdracht(TestOpdracht);
}
/// <summary>
///A test for Index
///</summary>
[TestMethod()]
public void CreateKlasDirectsToToonKlassen()
{
Klas Klas = new Klas { KlasNaam = "2dNet" };
RedirectToRouteResult view = Controller.Create(1) as RedirectToRouteResult;
Assert.IsNotNull(view);
Assert.AreEqual("ToonKlassen", view.RouteValues["action"]);
}
}
at the moment I get a nullreferenceException on the view (assert.isNotNull fails)
and here is one of my DummyRepository's:
class DummyOpdrachtRepository : IOpdrachtRepository
{
List<Opdracht> opdrachten;
public DummyOpdrachtRepository()
{
opdrachten = new List<Opdracht>();
}
public void addOpdracht(Opdracht opdracht)
{
opdrachten.Add(opdracht);
}
public string GetDocentID(int OpdrachtID)
{
var opdracht = opdrachten.Where(o => o.OpdrachtID == OpdrachtID).FirstOrDefault();
return opdracht.StamNummer;
}
public Opdracht Find(int id)
{
return opdrachten.Where(o => o.OpdrachtID == id).FirstOrDefault();
}
}
Normally I should have written the tests Before writting the code, I know (and I am convinced off TDD, as I have used it successfully in my latest Java-project). but it just doesn't seem to work..
here is the code for KlasController.Create action
public ActionResult Create(int id) //id = opdrachtID
{
var Opdracht = OpdrachtRepo.Find(id);
Vak vak;
if(Opdracht != null)
vak = Opdracht.Vak;
else
throw new NullReferenceException("Deze opdracht werd niet gevonden");
return View(new CreateKlasModel(id,vak));
}
I know this is a lot of code, but I really want to make this work.
Thanks for helping me out in advance :)
As vladimir77 already says in his comment, the method public ActionResult Create(int id) is of type ViewResult, so either you change you method to do areturn RedirectToRoute() or you change your test to
ViewResult view = Controller.Create(1);
Assert.IsNotNull(view);
A ViewResult can not be cast as a RedirectToRouteResult.

Moq SetupProperty not working

Can someone tell me whey the following code blows when the moq.SetupProperty fails in the code below:
[TestMethod]
public void SimulatorService_Returns_HighScores()
{
IScoreService scoreService = new ScoreService(MockScoreRepository.GetMockScoreRepository());
Assert.IsNotNull(scoreService);
var highScores = scoreService.GetHighScores();
Assert.IsTrue(highScores.Count > 0);
}
public static class MockScoreRepository
{
public static ScoreEntry GetMockScoreEntry(int seed)
{
var moq = new Mock<ScoreEntry>();
moq.SetupProperty(s => s.UserID, seed);
moq.SetupProperty(s => s.Score, 10 * seed);
moq.SetupProperty(s => s.EntryDate, DateTime.Now);
return moq.Object;
}
public static IScoreRepository GetMockScoreRepository()
{
var scores = new List<ScoreEntry>();
for (var i = 0; i < 20; i++)
{
scores.Add(GetMockScoreEntry(i));
}
var repository = new Mock<IScoreRepository>();
repository.Setup(r => r.GetScores()).Returns(scores.AsQueryable());
return repository.Object;
}
}
The first thing I'd check is to make sure that the properties of ScoreEntry that you're setting have accessible setters. In other words, make sure your setters have public access or that you at least have a setter for each property you're attempting to set through moq.

Resources