ASP. NET MVC2 Chapter IV II

Source: Internet
Author: User
Tags connectionstrings
§ 4. 5 setting up di

Before getting startedUnit Testing, It's worth putting yourDi infrastructure into place. This will dealResolving DependenciesBetween components. (e.g., productscontroller's dependency on an iproductsrepository) for this example, you'll use the popular open sourceDi container ninject, Which you'll configure by adding some code to yourGlobal. asax. CSFile.

ADi componentCan be any. net object or type that you choose. all your controllers are going to be di components, and so are your repositories. each time you instantiate a component, the di container will resolve its Dependencies automatically. so, if a controller depends on a repository-perhaps by demaning an instance as a constructor parameter-the di container will supply a suitable instance. once you see Code, you'll realize that it's actually quite simple!

First, download ninject from its web site, ninject.org/.10 all you need is its main assembly,Ninject. dll, So put this somewhere convenient on disk and then reference it from yourSportsstore. webuiProject

 

§ 4. 5.1 creating a custom controller Factory

first, create a new folder in your sportsstore. webui project called infrastructure . inside that folder, create a class called ninjectcontrollerfactory :

Namespace sportsstore. infrastructure {public class ninjectcontrollerfactory: defaultcontrollerfactory {// A ninject "kernel" is the thing that can supply object instances private ikernel kernel = new standardkernel (new kernel (); // ASP. net MVC callthis to get the Controller for each request protected override icontroller getcontrollerinstance (requestcontext context, type controllertype) {If (controllertype = NULL) return NULL; Return (icontroller) kernel. get (controllertype);} // configures how abstract service types are mapped to concrete implementations private class sportsstoreservices: ninjectmodule {public override void load () {// We'll add some configuration here in a moment }}}}

Next, instruct ASP. net mvc to use yourNew controller FactoryBy callingSetcontrollerfactory() Inside the application_start handler inGlobal. asax. CS:

§ 4. 5.2 using your di container

the whole point of bringing in a Di container is that you can use it to eliminate hard-coded dependencies between components . right now, you're going to eliminate productscontroller's current hard-coded dependency on sqlproductsrepository (which, in turn, means you'll eliminate the hardcoded connection string, soon to be configured elsewhere ). the advantages will soon become clear.
when a DI container instantiates an object (e.g ., A controller class), It inspects that type's list of constructor parameters (a.k. a. dependencies) and tries to supply a suitable object for each one. so, if you edit productscontroller , adding a new constructor parameter as follows:

Public productscontroller (iproductsrepository productsrepository) {// string connstring = "Data Source = (local) \ sql2005; initial catalog = sportsstore; Integrated Security = true;"; this. productsrepository = productsrepository ;}

Let us back to ninjectcontrollerfactory, and registered any iproductsrepository with the di container

 // configures how abstract service types are mapped to concrete implementations private class sportsstoreservices: ninjectmodule {public override void load () {bind 
   
     (). to 
    
      (). withconstructorargument ("connectionstring", configurationmanager. connectionstrings ["appdb"]. connectionstring) ;}}
    
   

As you can see, this code tries to fetch a connection string namedAppdbUsing. net's standard configurationmanager API, which in turn will look for it in your web. config file. to make this work, add a <connectionstrings> node inside web. config's root node, as follows:

 
<Connectionstrings> <Add name = "appdb" connectionstring = "Data Source = (local) \ sql2005; initial catalog = sportsstore; Integrated Security = true;"/> </connectionstrings>

So that's it-You 've set up a Working di System. No matter how does di components and dependencies you need to add, the plumbing is already done. Nothing chaged like before

 

 

§ 4. 5 creating Unit Tests

Almost all the foundational piecesInfrastructureAre now in place-A solution and project structure,A basic domain modelAndLINQ to SQL RepositorySystem,Di container-So now you can do the real job of writing applicationBehavior and tests!

ProductscontrollerCurrently produces a list of every product, Let us improve it into a paged list of products. In this section we'll combineNunit, Moq, And your component-oriented architecture to design new application behaviors using unit tests, starting with that paged list.

 

TDD: getting started

DownloadNunitFrom www.nunit.org andMoqFrom http://code.google.com/p/moq.

And addReferencesFrom yourSportsstore. unittestsProject to all these assemblies:

 

Choosing our own syntax

To make our unit tests easier to understand at a glance, we'll build upA small library of static methodsThat enable a readable ASP. net mvc unit testing syntax.

Namespace sportsstore. unittests {public static class unittesthelpers {public static void shouldequal <t> (this t actualvalue, t expectedvalue) {assert. areequal (Region, actualvalue );}}}
 
 
 
 
Adding the first unit test

To hold the first unit test, create a new class calledCatalogbrowsingIn yourSportsstore. unittestsProject.

FollowingBDD ideaOf describe a behavior, our first test will be calledCan_view_a_single_page_of_products

Namespace sportsstore. unittests {[testfixture] public class catalogbrowsing {[test] public void can_view_a_single_page_of_products () {// arrange: if there are 5 products in the repository... iproductsrepository repository = unittesthelpers. mockproductsrepository (New Product {name = "p1"}, new product {name = "p2"}, new product {name = "P3 "}, new product {name = "P4"}, new product {name = "P5"}); var controller = new productscontroller (repository); controller. pagesize = 3; // This property doesn't yet exist, but by // accessing it, you're implicitly forming // a requirement for it to exist // Act :... then when the user asks for the second page (pagesize = 3 )... vaR result = controller. list (2); // assert :... they'll just see the last two products. vaR displayedproducts = (ilist <product>) result. viewdata. model; displayedproducts. count. shouldequal (2); displayedproducts [0]. name. shouldequal ("P4"); displayedproducts [1]. name. shouldequal ("P5 ");}}}

To obtain a mock repository, it tries to callUnittesthelpers. mockproductsrepository ()

 
Public static parameter mockproductsrepository (Params product [] prods) {// generate an implementer of parameter at runtime using Moq var mockproductsrepos = new mock <iproductsrepository> (); mockproductsrepos. setup (x => X. products ). returns (prods. asqueryable (); Return mockproductsrepos. object ;}

It's far easier, tidier, and faster to do this than to actually load real rows into a SQL Server database for testing, and it's only possible because productscontroller accesses its repository only through an abstract interface.

 

 

Check that you have a red light first

 

Running the test suite in nunit Gui

Now you can add the paging behavior for real. this used to be a tricky task before LINQ (yes, SQL Server 2005 can return paged data sets, but it's hardly obvious how to do it ), but with LINQ it's a single, elegant C # code statement. update the list () method once again:

 
Public viewresult list (INT page) {return view (productsrepository. products. tolist (). skip (page-1) * pagesize ). take (pagesize ). tolist ());}

 

now, if you're doing unit tests, recompile and rerun the test in nunit gui. Behold... a green light!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.