Writing Useful Unit Tests - asp.net

I have a simple page with a Grid that I'm binding a collection of objects to. I also have some simple functionality on the grid to edit and save rows. I would like to write unit tests for this page, but it's not really making sense to me.
For example:
Private Sub LoadGrid()
'Populate Collection
grid.datasource = MyCollection
grid.databind()
end sub
I guess a Sub really doesn't need a unit test, but what if this were a function that returned true when the grid had been loaded. How do you write a unit test for this? What other test should be done on a simple web page like this?
As always, thanks to everyone who give any sort of input.

How do you write a unit test for this?
The first step is actually making your form testable. Have a look at this page for separating UI and BL layers, there are about a bajillion different ways to implement MVC, MVP, and all of its variants, and there's no One True Way™ to do it. So long as your code is sane and consistent, other people will be able to work on your code.
I personally find the following pattern works in most cases for testing UIs:
Create an interface representing your Model.
Create a class for your controller which handles all the updates to the model.
Your view should listen to changes to the model.
So in the end, you end up with something like this (sorry, my VB-fu is rusty, writing this in C# instead):
interface IProductPageModel
{
int CurrentPage { get; set; }
int ItemsPerPage { get; set; }
DataSet ProductDataSet { get; set; }
}
class ProductPageController
{
public readonly IProductPageModel Model;
public ProductPageController(IProductPageModel model)
{
this.Model = model;
}
public void NavigateTo(int page)
{
if (page <= 0)
throw new ArgumentOutOfRangeException("page should be greater than 0");
Model.CurrentPage = page;
Model.ProductDataSet = // some call to retrieve next page of data
}
// ...
}
This is concept code, of course, but you can see how its very easy to unit test. In principle, you could re-use the same controller code in for desktop apps, silverlight, etc since your controller doesn't depend directly on any particular view implementation.
And finally on your form side, you'd implement your page similar to:
public class ProductPage : Page, IProductPageModel
{
ProductPageController controller;
public ProductPage()
{
controller = new ProductPageController(this);
}
public DataSet ProductDataSet
{
get { return (DataSet)myGrid.DataSource; }
set { myGrid.DataSource = value; myGrid.DataBind(); }
}
protected void NavigateButton_OnCommand(object sender, CommandEventArgs e)
{
controller.NavigateTo(Convert.ToInt32(e.CommandArgument));
}
}
Here there's no real distinction between view and model -- they're the same entity. The idea is to make your code-behind as "stupid" as possible, so that as much testable business logic is contained in the controller as possible.
What other test should be done on a
simple webpage like this?
You'd want tests for any sort of form validation, you want to make sure you're throwing exceptions in exceptional cases, ensuring that your controller methods update your model in an expected way, and so on.

Juliet is right.
The line of code where you said
'Populate Collection
that is the testable part. You can do assertions on if the collection is null, if it has items, if it has exactly 42 items. But that would be an integration test.
If you can isolate all the calls to the database (the part that returns a datareader), then return a empty, fake DbDataReader, then you can test everything inbetween the UI and the database.
Tests that spin up a browser and verify that a table is render, similarly is a integration test that will depend on having IIS up and working (and a DB up and working, unless you have a repository you can fake)
If you are just getting started, I would look for all the easy to test code first, such as methods that do have dependencies on the database, then move on the tricker tests that require mocking/stubbing/faking database servers, etc.

Related

2 Different Models Need to Utilize Same View

Let me premise this by saying I am transitioning from Classic ASP to .net so my .net knowledge is all through books, not use. I am working on a shopping cart platform and have been tasked with creating 3 different display types (horizontal slider, vertical slider and grid) that will be able to be utilized by 2 different models.
I got the new views to work with my first model and thought I was in the clear and plugged in the second, but then I started getting an error about the models not being the same. I am trying to figure out what the best way to handle this. The solutions I have come up with are
Using A View Model - this seems like it is supposed to only be used when you need to combine 2 models into one and that is really the opposite of what I need, I need to make 1 view work for 2 models.
Make separate views for each type. This seems logical but is going to result in 5 new view files that are almost identical to those I have already created, it seemed redundant.
Use renderPartial and convert the models - not really sure how I would even accomplish this, but my though was to renderpartial out the creation of the actual displays (horizontal slider, vertical slider and grid view)
I am having a hard time determining what the best course of action is. I know that with MVC and .net you are supposed to never code the same thing twice and I think making the separate views is doing exactly that. Any thoughts on how to best approach this would be greatly appreciated.
This is the way I'm doing it right now on my project, I don't know if it's the best way or not but for me works fine.
Basically on my website's homepage I need to have to 2 different models to handle 2 forms posting to the same Method in the controller
namespace Website.Models.ViewModels
{
public class HomePageModels
{
public SearchFlyModel SearchFly { get; set; }
public CarRequestModel CarRequest { get; set; }
public int form { get; set; }
public HomePageModels()
{
SearchFly = new SearchFlyModel();
CarRequest = new CarRequestModel();
}
}
}
Then on the controller's method I need to know which form was posted to know which form I need to validate, because Asp.net automatically validate the model , it will ,by default validate both models in your ViewModel , and this affects the ModelState and when you check if your model is valid doing ModelState.isValid , this will return false because you only posted one form and not the other which is completely empty.
To manage that, I do the following
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(HomePageModels model)
{
ModelState.Clear();
if (model.form == 0)
{
try
{
ValidateModel(model.SearchFly);
return this.SearchFly(model.SearchFly);
}
catch (Exception e)
{
}
}
else
{
try
{
ValidateModel(model.CarRequest);
return this.SearchCar(model.CarRequest);
}
catch (Exception e)
{
}
}
var modelHomePage = new HomePageModels()
{
SearchFly = model.SearchFly,
CarRequest = model.CarRequest,
form=model.form
};
return View(modelHomePage);
}
Both forms are posting to the same action because I need to return the form's validations error so the user can fix it.

Passing data between views and models in Flex MVC framework

I have never used Flex/Actionscript before so excuse me if I'm asking anything obvious but I have been working on this for 3 days (includes searching google and stackoverflow) before writing this post.
I have been asked to modify a game written in Flex 4 made with a mini-IoC-based MVC framework. Two mods I have been asked to make is a game over screen, which displays the final score and a difficulty selection on the introduction screen. I have made the game over screen, and successfully managed to get the controller to bring it up when the game timer runs out.
So for now, the game structure goes:
Intro View -> Game View -> Game Over View
^ |
|__________ (retry?) ________|
The first problem is getting the score to be passed from the mainGame ActionScript file to the game over screen.
Things I have tried:
Importing mainGame in the gameOverViewBase and calling the mainGame.score variable in the gameOverView mxml file.
-EDIT!!! = the above method works if I change the score variable in mainGame to a constant, but if it remains a variable, the controller won't load the gameOverView and the game sits at an empty mainGame view.
Making a function that adds to a new score variable in the gameOverViewBase whenever the player scores during the game.
Passing the score as a parameter to the GameOverView when the MainGame ends
controller.loadGameOver(score);
This seemed like the most logical way to go about it. So I followed the function through the other components of the game setting the loadGameOver to take an integer as a parameter until I got to the main game actionscript file:
public function loadGameOver(score:int) : void
{
loadView(GameOverView);
}
The loadView function (shown below) is where I get stuck because I can't see where to pass the 'score' parameter. It looks like this:
private function loadView(viewClass:Class, modelClass:Class = null) : void
{
var view:View = new viewClass();
if(!view) throw new Error("Could not load view");
viewContainer.removeAllElements();
viewContainer.addElement(view);
view.controller = this;
}
The second problem is the difficulty selection on the introduction screen. I have done this with 3 buttons (easy, normal, hard) in the mxml file and for every button in the ActionScript:
protected function onEasyButtonClick() : void
{
set = "easy"
controller.loadMainGame(set);
}
Once again, I end up at the above loadView function.
To sum up: I need to know how to pass the data between the views and models. If that's not the ideal method, I am open to any other methods that you think are better.
Thank You!
Ben
P.S. I can send my source code to anyone who would like to help :)
You don't specify which MVC framework you're using which would be helpful. However, score should definitely be a property of a model and the model data should be accessible to the view either directly, perhaps via binding (thanks weltraumpirat), or via some intermediary class.
I would suggest you have a look at some of the existing view classes and try to figure out how they are fed the model data. You can use this approach to get the data you need for your view.
[EDIT]:
The mainGame property is not being set on your GameOverView instance so you're unable to access its score property either through binding or through trace. The loadView method of your controller class accepts a Model class reference which it uses to construct a new Model instance to be used by the new View. Unfortunately this is no use to you as your GameOverView needs the instance of MainGame which was created for the MainGameView (and which contains the current score).
I don't know if the following fits into the philosophy of the framework you're using. However, I would change the loadView method to accept an instance of a Model rather than a class reference, and create and cache a reference to an instance of MainGame when your controller is instantiated. That way you can pass the same Model reference to both the MainGameView and GameOverView when these are created.
public class WhackAMoleBase extends Application implements IGameController
{
public var viewContainer:Group;
private var mainGame:MainGame
public function WhackAMoleBase() : void
{
super();
// Create and cache an instance of the main game Model
mainGame = new MainGame();
addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
public function loadIntroduction() : void
{
loadView(IntroductionView);
}
public function loadMainGame() : void
{
loadView(MainGameView, mainGame);
}
public function loadGameOver() : void
{
// Use the same instance of MainGame which the MainGameView
// has been using as the Model for the GameOverView
loadView(GameOverView, mainGame);
}
// Accept a Model instance rather than a class Reference
private function loadView(viewClass:Class, model:Model = null) : void
{
//Create a new instance of the supplied view
var view:View = new viewClass();
if(!view) throw new Error("Could not load view");
//Clear any previous views in the container and add
viewContainer.removeAllElements();
viewContainer.addElement(view);
//Property based dependency injection
view.controller = this;
//There may or may not be a model required for the
//requested view; check and instantiate appropriately
if(model)
{
//Give model reference to the controller
//and link the view up to the model
model.controller = this;
view.model = model;
}
}
private function onCreationComplete(event:FlexEvent) : void
{
//When the application is first created, we want to show the introductory view
loadView(IntroductionView);
}
}

ASP.NET web user control best practise

I'm building some web user controls and just wondering what is the right / best practice approach to implement properties. In this example he control is a "score card" control which has to display a score ( and it also has to do other stuff) ....to make things easier I made these code samples very simple but in reality my control does other stuff as well with the score besides displaying it in a label :-)
Choice #1
private int _score;
public int Score
{
get { return _score; }
set { _score = value; Refresh(); }
}
public void Refresh()
{
lblScore.Text = Score;
}
Choice #2:
public int Score {get;set;}
protected void PageLoad(object sender, EventArgs e)
{
Refresh();
}
private void Refresh()
{
lblScore.Text = Score;
}
Choice #3:
public int Score
{
get { lblScore.Text; }
set { lblScore.Text = value; }
}
So , of course, the question is what is the best practice way of implementing the Score property of the control ....:-)
MadSeb
Choice 1
Choice 2 is out of this because you should not link initialization and functionality to specific page events in a UserControl. That is a source for nasty errors related to Page-Lifecycle. You might want to make modifications after Page_Load(f.e. in a Button's Click-Event in the page) but it's too late for the implicit Refresh.
Choice 3 is out because for simply setting the Text of a Label you don't want somebody to remember that he has to call Refresh after he has set the Score. But that depends on how expensive "my control does other stuff as well with the score besides displaying it in a label" is. If you often change the Score but not necessarily need to refresh immediately, i would do the Refresh after all initialization has done.
In my opinion a UserControl should encapsulate complexity as long as it keeps enough flexibility and control to be reusable. Don't do too much "magic" things in the background that might cause errors in different conditions that you won't find quickly. That is particularly so in a Setter what normally only should set the corresponding variable.
There are two different use cases for an UserControl:
Reusability.
If your control contains only few controls but you want to reuse it many times, i would let the controller get/set properties and don't do complex things in it that depend on specific conditions. That would reduce reusability. You might want to provide clear methods and events that the controller could handle.
Container.
If your control behaves similar to a page and has a lot of controls and functionality, it should do most of all by itself. You only want to provide a few methods and events(that don't have to be handled necessarily). The most important method in this case would be e.g. a public void BindData() that does all initialization after the controller has set the necessary variables. That is the replacement for your Choice 2.
Note: if your score is stored in lblScore.Text as string anyway, i would prefer using the Text property of the label instead of creating another int-variable(cast it to an int in the getter). That has the advantages that you don't need to store your variable in ViewState manually, because it's already stored. On this way you don't need to set it on every postback.

Intercept Unity 2.0 HandlerAttribute without an interface

I'm a first-time user of the AOP features of Unity 2.0 and would like some advice. My goal is to be able to log method calls in an ASPX page, like so:
public partial class Page2 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[Log]
private void Testing()
{
}
}
Here is the code for the LogAttribute:
public class LogAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogHandler(Order);
}
}
Now the LogHandler:
public class LogHandler : ICallHandler
{
public LogHandler(int order)
{
Order = order;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
string className = input.MethodBase.DeclaringType.Name;
string methodName = input.MethodBase.Name;
string preMethodMessage = string.Format("{0}.{1}", className, methodName);
System.Diagnostics.Debug.WriteLine(preMethodMessage);
return getNext()(input, getNext);
}
public int Order { get; set; }
}
The problem I have is how to use the [Log] attribute. I've seen plenty of example of how to configure the interception settings, for example:
container.AddNewExtension<Interception>();
container.Configure<Interception>().SetDefaultInterceptorFor<ILogger>(new InterfaceInterceptor());
But this implies that I have an interface to intercept, which I don't. I have the ASPX page which uses the [Log] attribute.
so how can I configure Unity to make use of the [Log] attribute? I've done this before using PostSharp and would like to be able to use Unity to do the same.
Cheers.
Jas.
You're unfortunately not going to get this to work in an ASP.NET page with Unity interception.
Unity interception uses a runtime interception model. Depending on the interceptor you choose, you'll either get a subclass with virtual method overrides to call the call handlers (VirtualMethodInterceptor) or a separate proxy object (Interface or TransparentProxyInterceptor) which execute the call handlers and then forward to the real object.
Here's the issue - ASP.NET controls creation and calls to your page, and there's no easy way to hook into them. Without controlling the creation of the page object, you can't use the VirtualMethodInterceptor, because that requires that you instantiate a subclass. And you can't use the proxy version either, because you need ASP.NET to make calls through the proxy.
PostSharp gets around this because it's actually rewriting your IL at compile time.
Assuming you could hook into the creation of the page object, you'd have to use the VirtualMethodInterceptor here. It's a private method, so you want logging on "self" calls (calls from one method of the object into another method on the same object). The proxy-based interceptors can't see those, since the proxy is a separate instance.
I expect there is a hook somewhere to customize how ASP.NET creates object - BuildManager maybe? But I don't know enough about the details, and I expect it'll require some pretty serious hacking to get work.
So, how do you get around this? My recommendation (actually, I'd recommend this anyway) is to use the Model-View-Presenter pattern for your ASP.NET pages. Make the page object itself dumb. All it does is forward calls to a separate object, the Presenter. The Presenter is where your real logic is, and is independent of the details of ASP.NET. You get a huge gain in testability, and you can intercept calls on the presenter without all the difficulty that ASP.NET gives you.

linq-to-sql "an attempt has been made to attach or add an entity that is not new"?

I've been getting several errors:
cannot add an entity with a key that is already in use
An attempt has been made to attach or add an entity that is not new, perhaps having been loaded from another datacontext
In case 1, this stems from trying to set the key for an entity versus the entity. In case 2, I'm not attaching an entity but I am doing this:
MyParent.Child = EntityFromOtherDataContext;
I've been using using the pattern of wrap everything with a using datacontext. In my case, I am using this in a web forms scenario, and obviously moving the datacontext object to a class wide member variables solves this.
My questions are thus 2 fold:
How can I get rid of these errors and not have to structure my program in an odd way or pass the datacontext around while keeping the local-wrap pattern? I assume I could make another hit to the database but that seems very inefficient.
Would most people recommend that moving the datacontext to the class wide scope is desirable for web pages?
Linq to SQL is not adapted to disconnected scenarios. You can copy your entity to a DTO having a similar structure as the entity and then pass it around. Then copy the properties back to an entity when it's time to attach it to a new data context. You can also deserialize/reserialize the entity before attaching to a new data context to have a clean state. The first workaround clearly violates the DRY principle whereas the second is just ugly. If you don't want to use any of these solution the only option left is to retrieve the entity you're about to modify by its PK by hitting the DB. That means an extra query before every update. Or use another ORM if that's an option for you. Entity Framework 4 (included with .NET 4) with self-tracking entities is what I'm using currently on a web forms project and everything is great so far.
DataContext is not thread-safe and should only be used with using at the method level, as you already do. You can consider adding a lock to a static data context but that means no concurrent access to the database. Plus you'll get entities accumulated in memory inside the context that will turn into potential problems.
For those that came after me, I'll provide my own take:
The error "an attempt has been made to add or attach an entity that is not new" stems from this operation:
Child.Parent = ParentEntityFromOtherDataContext
We can reload the object using the current datacontext to avoid the problem in this way:
Child.Parent = dc.Entries.Select(t => t).Where(t => t.ID == parentEntry.ID).SingleOrDefault();
Or one could do this
MySubroutine(DataContext previousDataContext)
{
work...
}
Or in a web forms scenario, I am leaning to making the DataContext a class member such as this:
DataContext _dc = new DataContext();
Yes, the datacontext is suppose to represent a unit of work. But, it is a light-weight object and in a web forms scenario where a page is fairly transient, the pattern can be changed from the (using dc = new dc()) to simply using the member variable _dc. I am leaning to this last solution because it will hit the database less and require less code.
But, are there gotchas to even this solution? I'm thinking along the lines of some stale data being cached.
What I usually do is this
public abstract class BaseRepository : IDisposable
{
public BaseRepository():
this(new MyDataContext( ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString))
{
}
public BaseRepository(MyDataContext dataContext)
{
this.DataContext = dataContext;
}
public MyDataContext DataContext {get; set;}
public void Dispose()
{
this.DataContext.Dispose();
}
}
Then imagine I have the following repository
public class EmployeeRepository : BaseRepository
{
public EmployeeRepository():base()
{
}
public EmployeeRepository(MyDataContext dataContext):base(dataContext)
{
}
public Employee SelectById(Guid id)
{
return this.DataContext.Employees.FirstOrDefault(e=>e.Id==id);
}
public void Update(Employee employee)
{
Employee original = this.Select(employee.Id);
if(original!=null)
{
original.Name = employee.Name;
//others
this.DataContext.SubmitChanges();
}
}
}
And in my controllers (I am using asp.net mvc)
public ActionResult Update(Employee employee)
{
using(EmployeeRepository employeeRepository = new EmployeeRepository())
{
if(ModelState.IsValid)
{
employeeRepository.Update(employee);
}
}
//other treatment
}
So the datacontext is properly disposed and I can use it across the same instance of my employee repository
Now imagine that for a specific action I want the employee's company to be loaded (in order to be displyed in my view later), I can do this:
public ActionResult Select(Guid id)
{
using(EmployeeRepository employeeRepository = new EmployeeRepository())
{
//Specifying special load options for this specific action:
DataLoadOptions options = new DataLaodOptions();
options.LoadWith<Employee>(e=>e.Company);
employeeRepository.DataContext.LoadOptions = options;
return View(employeeRepository.SelectById(id));
}
}

Resources