TDD problem in ASP.NET MVC3 (with DI) - asp.net

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.

Related

How to unit test the controller?

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

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.

Moq VerifySet(Action) strange behaviour

I use Moq to test some behaviour. I want to verify set view's model property as new instance of Message class:
[TestFixture]
public class MessageFormPresenterTests
{
private NameValueCollection queryString;
private Mock<IDatabase> mockDatabase;
private Mock<HttpContextBase> mockHttpContext;
private Mock<HttpRequestBase> mockRequest;
private Mock<HttpResponseBase> mockResponce;
private Mock<IMessageFormView> mockView;
private MessageFormPresenter presenter;
[SetUp]
public void SetUp()
{
this.queryString = new NameValueCollection();
this.mockDatabase = new Mock<IDatabase>();
this.mockHttpContext = new Mock<HttpContextBase>();
this.mockRequest = new Mock<HttpRequestBase>();
this.mockResponce = new Mock<HttpResponseBase>();
this.mockView = new Mock<IMessageFormView>();
this.mockHttpContext.SetupGet(c => c.Request).Returns(this.mockRequest.Object);
this.mockHttpContext.SetupGet(c => c.Response).Returns(this.mockResponce.Object);
this.mockRequest.SetupGet(r => r.QueryString).Returns(this.queryString);
this.presenter = new MessageFormPresenter(this.mockView.Object) { Database = this.mockDatabase.Object, HttpContext = this.mockHttpContext.Object };
}
[Test]
public void ViewLoad_QueryStringNotHasMessageIdParameter_PopulateViewModelAsNewMessage()
{
// Act
this.mockView.Raise(v => v.Load += null, new EventArgs());
// Assert
this.mockView.VerifySet(v => v.Model = It.Is<Message>(m => m.Id == 0));
}
}
But this test pass even if i not write this functionality in my MessageFormPresenter. When i set breakpoint to action call (v.Model = It.Is(m => m.Id == 0)) and debug my test, Model property returned as "Castle.Proxies.MessageProxy" type and has all properties with default values (value of Id property is 0, of course).
Why is this happening? I don't setup anything to return and Moq should return null by default.
P.S. Excuse me for my poor english. I hope you understand what i'm talking about)
UPDATE1: MessageFormPresenter class:
public class MessageFormPresenter : Presenter<IMessageFormView>
{
private IDatabase database;
public MessageFormPresenter(IMessageFormView view)
: base(view)
{
View.Load += this.View_Load;
}
public IDatabase Database
{
get { return this.database ?? (this.database = DatabaseFactory.DatabaseInstance); }
set { this.database = value; }
}
private void View_Load(object sender, EventArgs e)
{
int messageId;
var messageParam = Request.QueryString[QueryParamNames.MessageId];
if (messageParam == null)
{
View.Model = new Message();
return;
}
if (!View.IsAdmin)
{
Response.Redirect(PageUrls.AccessDenied, true);
return;
}
if (int.TryParse(
messageParam,
NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite,
CultureInfo.InvariantCulture,
out messageId))
{
View.Model = this.Database.Single<Message>(messageId);
}
else
{
Response.Redirect(PageUrls.DefaultPage, true);
}
}
}
Base class Presenter<IMessageFormView> provided by WebFormsMvp framework.
UPDATE2: If i use strict behaviour TargetInvocationException will be thrown in base constructor of MessageFormPresenter, even if i setup all properties of Mock<IMessageFormView>.

Any reason why this LINQ to SQL update query is not working . .

Somehow this update code is not working:
Here is my Controller code:
private UserRepository repo = new UserRepository();
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, UserInfo user_)
{
try
{
repo.UpdateUser(user_);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Here is the repo code that is used above (UserRepository)
private UsersDataContext db = new UsersDataContext();
public void UpdateUser(UserInfo user_)
{
UserInfo origUser = GetUser(user_.Id);
origUser.First = user_.First;
origUser.Last = user_.Last;
origUser.City = user_.City;
origUser.Country = user_.Country;
origUser.State = user_.State;
origUser.Street_Address = user_.Street_Address;
db.SubmitChanges();
}
public UserInfo GetUser(int id_)
{
return db.UserInfos.SingleOrDefault(d => d.Id == id_);
}
EDIT:
Note that when debugging everything is running fine (no exceptions) but when it redirects back to Index the data has not been updated when the changes from the update.
i just changed the userrepository to the following:
private UsersDataContext db = new UsersDataContext();
public void UpdateUser(UserInfo user_)
{
UserInfo origUser = db.UserInfos.SingleOrDefault(d => d.Id == id_);
origUser.First = user_.First;
origUser.Last = user_.Last;
origUser.City = user_.City;
origUser.Country = user_.Country;
origUser.State = user_.State;
origUser.Street_Address = user_.Street_Address;
db.SubmitChanges();
}
so all i did was move the GetUser() method inline and it worked.
It might have been a red herring and it was just a caching issue . .
You don't mention how you've defined UserInfo, is it a struct or a class?
If it's a struct, returning it from GetUser will create a new object and thus you will not update the database object, only a local copy of it.
Moving the GetUser inline avoid this temp copy creation and that's likely why it's working.
afaik you could do something like
public void GetUser(int id_, out UserInfo user_)
{
user_ = db.UserInfos.SingleOrDefault(d => d.Id == id_);
}
You would then call it like this
public void UpdateUser(UserInfo user_)
{
UserInfo origUser;
GetUser(user_.Id, out origUser);
origUser.First = user_.First;
origUser.Last = user_.Last;
origUser.City = user_.City;
origUser.Country = user_.Country;
origUser.State = user_.State;
origUser.Street_Address = user_.Street_Address;
db.SubmitChanges();
}
Maybe you disabled Object Tracking?

Resources