├── .gitattributes
├── .gitignore
├── .nuget
├── NuGet.Config
├── NuGet.exe
└── NuGet.targets
├── README.md
├── UnitTestingWebAPI.API.Core
├── App.config
├── Controllers
│ ├── ArticlesController.cs
│ └── BlogsController.cs
├── CustomAssembliesResolver.cs
├── Filters
│ └── ArticlesReversedFilter.cs
├── MediaTypeFormatters
│ └── ArticleFormatter.cs
├── MessageHandlers
│ ├── EndRequestHandler.cs
│ └── HeaderAppenderHandler.cs
├── Properties
│ └── AssemblyInfo.cs
├── UnitTestingWebAPI.API.Core.csproj
└── packages.config
├── UnitTestingWebAPI.API
├── Global.asax
├── Global.asax.cs
├── Properties
│ └── AssemblyInfo.cs
├── Startup.cs
├── UnitTestingWebAPI.API.csproj
├── Web.Debug.config
├── Web.Release.config
├── Web.config
└── packages.config
├── UnitTestingWebAPI.Data
├── App.config
├── BloggerEntities.cs
├── BloggerInitializer.cs
├── Configurations
│ ├── ArticleConfiguration.cs
│ └── BlogConfiguration.cs
├── Infrastructure
│ ├── DbFactory.cs
│ ├── Disposable.cs
│ ├── IDbFactory.cs
│ ├── IRepository.cs
│ ├── IUnitOfWork.cs
│ ├── RepositoryBase.cs
│ └── UnitOfWork.cs
├── Properties
│ └── AssemblyInfo.cs
├── Repositories
│ ├── ArticleRepository.cs
│ └── BlogRepository.cs
├── UnitTestingWebAPI.Data.csproj
└── packages.config
├── UnitTestingWebAPI.Domain
├── Article.cs
├── Blog.cs
├── Properties
│ └── AssemblyInfo.cs
└── UnitTestingWebAPI.Domain.csproj
├── UnitTestingWebAPI.Service
├── ArticleService.cs
├── BlogService.cs
├── Properties
│ └── AssemblyInfo.cs
└── UnitTestingWebAPI.Service.csproj
├── UnitTestingWebAPI.Tests
├── ActionFilterTests.cs
├── App.config
├── ControllerTests.cs
├── Helpers
│ └── ControllerActionSelector.cs
├── Hosting
│ └── Startup.cs
├── MediaTypeFormatterTests.cs
├── MessageHandlerTests.cs
├── Properties
│ └── AssemblyInfo.cs
├── RouteTests.cs
├── ServicesTests.cs
├── UnitTestingWebAPI.Tests.csproj
└── packages.config
├── UnitTestingWebAPI.sln
└── licence
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # Roslyn cache directories
20 | *.ide/
21 |
22 | # MSTest test Results
23 | [Tt]est[Rr]esult*/
24 | [Bb]uild[Ll]og.*
25 |
26 | #NUNIT
27 | *.VisualState.xml
28 | TestResult.xml
29 |
30 | # Build Results of an ATL Project
31 | [Dd]ebugPS/
32 | [Rr]eleasePS/
33 | dlldata.c
34 |
35 | *_i.c
36 | *_p.c
37 | *_i.h
38 | *.ilk
39 | *.meta
40 | *.obj
41 | *.pch
42 | *.pdb
43 | *.pgc
44 | *.pgd
45 | *.rsp
46 | *.sbr
47 | *.tlb
48 | *.tli
49 | *.tlh
50 | *.tmp
51 | *.tmp_proj
52 | *.log
53 | *.vspscc
54 | *.vssscc
55 | .builds
56 | *.pidb
57 | *.svclog
58 | *.scc
59 |
60 | # Chutzpah Test files
61 | _Chutzpah*
62 |
63 | # Visual C++ cache files
64 | ipch/
65 | *.aps
66 | *.ncb
67 | *.opensdf
68 | *.sdf
69 | *.cachefile
70 |
71 | # Visual Studio profiler
72 | *.psess
73 | *.vsp
74 | *.vspx
75 |
76 | # TFS 2012 Local Workspace
77 | $tf/
78 |
79 | # Guidance Automation Toolkit
80 | *.gpState
81 |
82 | # ReSharper is a .NET coding add-in
83 | _ReSharper*/
84 | *.[Rr]e[Ss]harper
85 | *.DotSettings.user
86 |
87 | # JustCode is a .NET coding addin-in
88 | .JustCode
89 |
90 | # TeamCity is a build add-in
91 | _TeamCity*
92 |
93 | # DotCover is a Code Coverage Tool
94 | *.dotCover
95 |
96 | # NCrunch
97 | _NCrunch_*
98 | .*crunch*.local.xml
99 |
100 | # MightyMoose
101 | *.mm.*
102 | AutoTest.Net/
103 |
104 | # Web workbench (sass)
105 | .sass-cache/
106 |
107 | # Installshield output folder
108 | [Ee]xpress/
109 |
110 | # DocProject is a documentation generator add-in
111 | DocProject/buildhelp/
112 | DocProject/Help/*.HxT
113 | DocProject/Help/*.HxC
114 | DocProject/Help/*.hhc
115 | DocProject/Help/*.hhk
116 | DocProject/Help/*.hhp
117 | DocProject/Help/Html2
118 | DocProject/Help/html
119 |
120 | # Click-Once directory
121 | publish/
122 |
123 | # Publish Web Output
124 | *.[Pp]ublish.xml
125 | *.azurePubxml
126 | ## TODO: Comment the next line if you want to checkin your
127 | ## web deploy settings but do note that will include unencrypted
128 | ## passwords
129 | #*.pubxml
130 |
131 | # NuGet Packages Directory
132 | packages/*
133 | ## TODO: If the tool you use requires repositories.config
134 | ## uncomment the next line
135 | #!packages/repositories.config
136 |
137 | # Enable "build/" folder in the NuGet Packages folder since
138 | # NuGet packages use it for MSBuild targets.
139 | # This line needs to be after the ignore of the build folder
140 | # (and the packages folder if the line above has been uncommented)
141 | !packages/build/
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # LightSwitch generated files
187 | GeneratedArtifacts/
188 | _Pvt_Extensions/
189 | ModelManifest.xml
--------------------------------------------------------------------------------
/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chsakell/webapiunittesting/3a049cc8b1fa63f4bf4226588682eea27b8f3a19/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 |
32 |
33 |
34 |
35 | $(SolutionDir).nuget
36 |
37 |
38 |
39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config
40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
41 |
42 |
43 |
44 | $(MSBuildProjectDirectory)\packages.config
45 | $(PackagesProjectConfig)
46 |
47 |
48 |
49 |
50 | $(NuGetToolsPath)\NuGet.exe
51 | @(PackageSource)
52 |
53 | "$(NuGetExePath)"
54 | mono --runtime=v4.0.30319 "$(NuGetExePath)"
55 |
56 | $(TargetDir.Trim('\\'))
57 |
58 | -RequireConsent
59 | -NonInteractive
60 |
61 | "$(SolutionDir) "
62 | "$(SolutionDir)"
63 |
64 |
65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
67 |
68 |
69 |
70 | RestorePackages;
71 | $(BuildDependsOn);
72 |
73 |
74 |
75 |
76 | $(BuildDependsOn);
77 | BuildPackage;
78 |
79 |
80 |
81 |
82 |
83 |
84 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ASP.NET Web API Unit Testing
2 |
3 | [](https://github.com/chsakell/webapiunittesting/blob/master/licence)
4 |
5 | Blog post: ASP.NET Web API Unit Testing
6 |
7 |
Follow chsakell's Blog
8 |
9 |
10 |
11 | Facebook |
12 | Twitter |
13 |
14 |
15 |
16 |
17 | Microsoft Web Application Development |
18 |
19 |
20 |
21 |
22 |
23 |
24 | |
25 |
26 |
27 | |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/Controllers/ArticlesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity.Infrastructure;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Web.Http;
9 | using System.Web.Http.Description;
10 | using UnitTestingWebAPI.Domain;
11 | using UnitTestingWebAPI.Service;
12 |
13 | namespace UnitTestingWebAPI.API.Core.Controllers
14 | {
15 | public class ArticlesController : ApiController
16 | {
17 | private IArticleService _articleService;
18 |
19 | public ArticlesController(IArticleService articleService)
20 | {
21 | _articleService = articleService;
22 | }
23 |
24 | // GET: api/Articles
25 | public IEnumerable GetArticles()
26 | {
27 | return _articleService.GetArticles();
28 | }
29 |
30 | // GET: api/Articles/5
31 | [ResponseType(typeof(Article))]
32 | public IHttpActionResult GetArticle(int id)
33 | {
34 | Article article = _articleService.GetArticle(id);
35 | if (article == null)
36 | {
37 | return NotFound();
38 | }
39 |
40 | return Ok(article);
41 | }
42 |
43 | // PUT: api/Articles/5
44 | [ResponseType(typeof(void))]
45 | public IHttpActionResult PutArticle(int id, Article article)
46 | {
47 | if (!ModelState.IsValid)
48 | {
49 | return BadRequest(ModelState);
50 | }
51 |
52 | if (id != article.ID)
53 | {
54 | return BadRequest();
55 | }
56 |
57 | _articleService.UpdateArticle(article);
58 |
59 | try
60 | {
61 | _articleService.SaveArticle();
62 | }
63 | catch (DbUpdateConcurrencyException)
64 | {
65 | if (!ArticleExists(id))
66 | {
67 | return NotFound();
68 | }
69 | else
70 | {
71 | throw;
72 | }
73 | }
74 |
75 | return StatusCode(HttpStatusCode.NoContent);
76 | }
77 |
78 | // POST: api/Articles
79 | [ResponseType(typeof(Article))]
80 | public IHttpActionResult PostArticle(Article article)
81 | {
82 | if (!ModelState.IsValid)
83 | {
84 | return BadRequest(ModelState);
85 | }
86 |
87 | _articleService.CreateArticle(article);
88 |
89 | return CreatedAtRoute("DefaultApi", new { id = article.ID }, article);
90 | }
91 |
92 | // DELETE: api/Articles/5
93 | [ResponseType(typeof(Article))]
94 | public IHttpActionResult DeleteArticle(int id)
95 | {
96 | Article article = _articleService.GetArticle(id);
97 | if (article == null)
98 | {
99 | return NotFound();
100 | }
101 |
102 | _articleService.DeleteArticle(article);
103 |
104 | return Ok(article);
105 | }
106 |
107 | private bool ArticleExists(int id)
108 | {
109 | return _articleService.GetArticle(id) != null;
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/Controllers/BlogsController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Data.Entity.Infrastructure;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Web.Http;
10 | using System.Web.Http.Description;
11 | using UnitTestingWebAPI.Domain;
12 | using UnitTestingWebAPI.Service;
13 |
14 | namespace UnitTestingWebAPI.API.Core.Controllers
15 | {
16 | public class BlogsController : ApiController
17 | {
18 | private IBlogService _blogService;
19 |
20 | public BlogsController(IBlogService blogService)
21 | {
22 | _blogService = blogService;
23 | }
24 |
25 | // GET: api/Blogs
26 | public IEnumerable GetBlogs()
27 | {
28 | return _blogService.GetBlogs();
29 | }
30 |
31 | // GET: api/Blogs/5
32 | [ResponseType(typeof(Blog))]
33 | public IHttpActionResult GetBlog(int id)
34 | {
35 | Blog blog = _blogService.GetBlog(id);
36 | if (blog == null)
37 | {
38 | return NotFound();
39 | }
40 |
41 | return Ok(blog);
42 | }
43 |
44 | // PUT: api/Blogs/5
45 | [ResponseType(typeof(void))]
46 | public IHttpActionResult PutBlog(int id, Blog blog)
47 | {
48 | if (!ModelState.IsValid)
49 | {
50 | return BadRequest(ModelState);
51 | }
52 |
53 | if (id != blog.ID)
54 | {
55 | return BadRequest();
56 | }
57 |
58 | _blogService.UpdateBlog(blog);
59 |
60 | try
61 | {
62 | _blogService.SaveBlog();
63 | }
64 | catch (DbUpdateConcurrencyException)
65 | {
66 | if (!BlogExists(id))
67 | {
68 | return NotFound();
69 | }
70 | else
71 | {
72 | throw;
73 | }
74 | }
75 |
76 | return StatusCode(HttpStatusCode.NoContent);
77 | }
78 |
79 | // POST: api/Blogs
80 | [ResponseType(typeof(Blog))]
81 | public IHttpActionResult PostBlog(Blog blog)
82 | {
83 | if (!ModelState.IsValid)
84 | {
85 | return BadRequest(ModelState);
86 | }
87 |
88 | _blogService.CreateBlog(blog);
89 |
90 | return CreatedAtRoute("DefaultApi", new { id = blog.ID }, blog);
91 | }
92 |
93 | // DELETE: api/Blogs/5
94 | [ResponseType(typeof(Blog))]
95 | public IHttpActionResult DeleteBlog(int id)
96 | {
97 | Blog blog = _blogService.GetBlog(id);
98 | if (blog == null)
99 | {
100 | return NotFound();
101 | }
102 |
103 | _blogService.DeleteBlog(blog);
104 |
105 | return Ok(blog);
106 | }
107 |
108 | private bool BlogExists(int id)
109 | {
110 | return _blogService.GetBlog(id) != null;
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/CustomAssembliesResolver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Web.Http.Dispatcher;
8 | using UnitTestingWebAPI.API.Core.Controllers;
9 |
10 | namespace UnitTestingWebAPI.API.Core
11 | {
12 | public class CustomAssembliesResolver : DefaultAssembliesResolver
13 | {
14 | public override ICollection GetAssemblies()
15 | {
16 | var baseAssemblies = base.GetAssemblies().ToList();
17 | var assemblies = new List(baseAssemblies) { typeof(BlogsController).Assembly };
18 | baseAssemblies.AddRange(assemblies);
19 |
20 | return baseAssemblies.Distinct().ToList();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/Filters/ArticlesReversedFilter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Web.Http.Filters;
8 | using UnitTestingWebAPI.Domain;
9 |
10 | namespace UnitTestingWebAPI.API.Core.Filters
11 | {
12 | public class ArticlesReversedFilter : ActionFilterAttribute
13 | {
14 | public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
15 | {
16 | var objectContent = actionExecutedContext.Response.Content as ObjectContent;
17 | if (objectContent != null)
18 | {
19 | List _articles = objectContent.Value as List;
20 | if (_articles != null && _articles.Count > 0)
21 | {
22 | _articles.Reverse();
23 | }
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/MediaTypeFormatters/ArticleFormatter.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Net.Http;
9 | using System.Net.Http.Formatting;
10 | using System.Net.Http.Headers;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 | using UnitTestingWebAPI.Domain;
14 | #endregion
15 |
16 | namespace UnitTestingWebAPI.API.Core.MediaTypeFormatters
17 | {
18 | public class ArticleFormatter : BufferedMediaTypeFormatter
19 | {
20 | public ArticleFormatter()
21 | {
22 | SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/article"));
23 | }
24 |
25 | public override bool CanReadType(Type type)
26 | {
27 | return false;
28 | }
29 |
30 | public override bool CanWriteType(Type type)
31 | {
32 | //for single article object
33 | if (type == typeof(Article))
34 | return true;
35 | else
36 | {
37 | // for multiple article objects
38 | Type _type = typeof(IEnumerable);
39 | return _type.IsAssignableFrom(type);
40 | }
41 | }
42 |
43 | public override void WriteToStream(Type type,
44 | object value,
45 | Stream writeStream,
46 | HttpContent content)
47 | {
48 | using (StreamWriter writer = new StreamWriter(writeStream))
49 | {
50 | var articles = value as IEnumerable;
51 | if (articles != null)
52 | {
53 | foreach (var article in articles)
54 | {
55 | writer.Write(String.Format("[{0},\"{1}\",\"{2}\",\"{3}\",\"{4}\"]",
56 | article.ID,
57 | article.Title,
58 | article.Author,
59 | article.URL,
60 | article.Contents));
61 | }
62 | }
63 | else
64 | {
65 | var _article = value as Article;
66 | if (_article == null)
67 | {
68 | throw new InvalidOperationException("Cannot serialize type");
69 | }
70 | writer.Write(String.Format("[{0},\"{1}\",\"{2}\",\"{3}\",\"{4}\"]",
71 | _article.ID,
72 | _article.Title,
73 | _article.Author,
74 | _article.URL,
75 | _article.Contents));
76 | }
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/MessageHandlers/EndRequestHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Net.Http;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace UnitTestingWebAPI.API.Core.MessageHandlers
11 | {
12 | public class EndRequestHandler : DelegatingHandler
13 | {
14 | async protected override Task SendAsync(
15 | HttpRequestMessage request, CancellationToken cancellationToken)
16 | {
17 | if (request.RequestUri.AbsoluteUri.Contains("test"))
18 | {
19 | var response = new HttpResponseMessage(HttpStatusCode.OK)
20 | {
21 | Content = new StringContent("Unit testing message handlers!")
22 | };
23 |
24 | var tsc = new TaskCompletionSource();
25 | tsc.SetResult(response);
26 | return await tsc.Task;
27 | }
28 | else
29 | {
30 | return await base.SendAsync(request, cancellationToken);
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/MessageHandlers/HeaderAppenderHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace UnitTestingWebAPI.API.Core.MessageHandlers
10 | {
11 | public class HeaderAppenderHandler : DelegatingHandler
12 | {
13 | async protected override Task SendAsync(
14 | HttpRequestMessage request, CancellationToken cancellationToken)
15 | {
16 | HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
17 |
18 | response.Headers.Add("X-WebAPI-Header", "Web API Unit testing in chsakell's blog.");
19 | return response;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UnitTestingWebAPI.API.Core")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UnitTestingWebAPI.API.Core")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("c8fd4f89-a6d0-4186-a176-c95923596825")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/UnitTestingWebAPI.API.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {04D7AE21-CABB-44A5-882C-44890AA19092}
8 | Library
9 | Properties
10 | UnitTestingWebAPI.API.Core
11 | UnitTestingWebAPI.API.Core
12 | v4.5.1
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll
37 |
38 |
39 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll
40 |
41 |
42 | False
43 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
44 |
45 |
46 |
47 |
48 |
49 |
50 | False
51 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
52 |
53 |
54 | False
55 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | {004555f2-5b29-49d0-98fd-60d57e0de8aa}
80 | UnitTestingWebAPI.Domain
81 |
82 |
83 | {ea36fd16-a613-4f31-8bff-94ece2028a63}
84 | UnitTestingWebAPI.Service
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
93 |
94 |
95 |
96 |
103 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API.Core/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="UnitTestingWebAPI.API.Global" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Http;
6 | using System.Web.Security;
7 | using System.Web.SessionState;
8 | using UnitTestingWebAPI.Data;
9 |
10 | namespace UnitTestingWebAPI.API
11 | {
12 | public class Global : System.Web.HttpApplication
13 | {
14 |
15 | protected void Application_Start(object sender, EventArgs e)
16 | {
17 | // Init database
18 | System.Data.Entity.Database.SetInitializer(new BloggerInitializer());
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UnitTestingWebAPI.API")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UnitTestingWebAPI.API")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a8bc6242-6a19-4605-8b81-94809131d4b0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Startup.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using Autofac;
3 | using Autofac.Integration.WebApi;
4 | using Owin;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Web;
9 | using System.Web.Http;
10 | using System.Web.Http.Dispatcher;
11 | using UnitTestingWebAPI.API.Core;
12 | using UnitTestingWebAPI.API.Core.Controllers;
13 | using UnitTestingWebAPI.API.Core.MediaTypeFormatters;
14 | using UnitTestingWebAPI.Data.Infrastructure;
15 | using UnitTestingWebAPI.Data.Repositories;
16 | using UnitTestingWebAPI.Service;
17 | #endregion
18 |
19 | namespace UnitTestingWebAPI.API
20 | {
21 | public class Startup
22 | {
23 | public void Configuration(IAppBuilder appBuilder)
24 | {
25 | var config = new HttpConfiguration();
26 | config.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());
27 | config.Formatters.Add(new ArticleFormatter());
28 |
29 | config.Routes.MapHttpRoute(
30 | name: "DefaultApi",
31 | routeTemplate: "api/{controller}/{id}",
32 | defaults: new { id = RouteParameter.Optional }
33 | );
34 |
35 |
36 | // Autofac configuration
37 | var builder = new ContainerBuilder();
38 | builder.RegisterApiControllers(typeof(BlogsController).Assembly);
39 | builder.RegisterType().As().InstancePerRequest();
40 | builder.RegisterType().As().InstancePerRequest();
41 |
42 | //Repositories
43 | builder.RegisterAssemblyTypes(typeof(BlogRepository).Assembly)
44 | .Where(t => t.Name.EndsWith("Repository"))
45 | .AsImplementedInterfaces().InstancePerRequest();
46 | // Services
47 | builder.RegisterAssemblyTypes(typeof(ArticleService).Assembly)
48 | .Where(t => t.Name.EndsWith("Service"))
49 | .AsImplementedInterfaces().InstancePerRequest();
50 |
51 | IContainer container = builder.Build();
52 | config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
53 |
54 | appBuilder.UseWebApi(config);
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/UnitTestingWebAPI.API.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 |
8 |
9 | 2.0
10 | {6D9E0639-885F-4B25-A5C4-1BEA8CF2F8C4}
11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
12 | Library
13 | Properties
14 | UnitTestingWebAPI.API
15 | UnitTestingWebAPI.API
16 | v4.5.1
17 | true
18 |
19 |
20 |
21 |
22 | ..\
23 | true
24 |
25 |
26 | true
27 | full
28 | false
29 | bin\
30 | DEBUG;TRACE
31 | prompt
32 | 4
33 |
34 |
35 | pdbonly
36 | true
37 | bin\
38 | TRACE
39 | prompt
40 | 4
41 |
42 |
43 |
44 | ..\packages\Autofac.3.5.0\lib\net40\Autofac.dll
45 |
46 |
47 | ..\packages\Autofac.Mvc5.3.3.4\lib\net45\Autofac.Integration.Mvc.dll
48 |
49 |
50 | ..\packages\Autofac.WebApi2.3.4.0\lib\net45\Autofac.Integration.WebApi.dll
51 |
52 |
53 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll
54 |
55 |
56 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll
57 |
58 |
59 |
60 | ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
61 |
62 |
63 | ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll
64 |
65 |
66 | True
67 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
68 |
69 |
70 | False
71 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
72 |
73 |
74 | ..\packages\Owin.1.0\lib\net40\Owin.dll
75 |
76 |
77 |
78 | False
79 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | False
92 | ..\packages\Microsoft.AspNet.WebPages.3.1.0\lib\net45\System.Web.Helpers.dll
93 |
94 |
95 | False
96 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
97 |
98 |
99 | ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
100 |
101 |
102 | False
103 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll
104 |
105 |
106 | True
107 | ..\packages\Microsoft.AspNet.Mvc.5.1.0\lib\net45\System.Web.Mvc.dll
108 |
109 |
110 | False
111 | ..\packages\Microsoft.AspNet.Razor.3.1.0\lib\net45\System.Web.Razor.dll
112 |
113 |
114 | False
115 | ..\packages\Microsoft.AspNet.WebPages.3.1.0\lib\net45\System.Web.WebPages.dll
116 |
117 |
118 | False
119 | ..\packages\Microsoft.AspNet.WebPages.3.1.0\lib\net45\System.Web.WebPages.Deployment.dll
120 |
121 |
122 | False
123 | ..\packages\Microsoft.AspNet.WebPages.3.1.0\lib\net45\System.Web.WebPages.Razor.dll
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | Web.config
137 |
138 |
139 | Web.config
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | Global.asax
149 |
150 |
151 |
152 |
153 |
154 |
155 | {04d7ae21-cabb-44a5-882c-44890aa19092}
156 | UnitTestingWebAPI.API.Core
157 |
158 |
159 | {d9166d82-be4e-4664-bbcc-7d31c274cb92}
160 | UnitTestingWebAPI.Data
161 |
162 |
163 | {ea36fd16-a613-4f31-8bff-94ece2028a63}
164 | UnitTestingWebAPI.Service
165 |
166 |
167 |
168 | 10.0
169 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | True
179 | True
180 | 56032
181 | /
182 | http://localhost:56032/
183 | False
184 | False
185 |
186 |
187 | False
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
196 |
197 |
198 |
199 |
206 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.API/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/BloggerEntities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using UnitTestingWebAPI.Data.Configurations;
8 | using UnitTestingWebAPI.Domain;
9 |
10 | namespace UnitTestingWebAPI.Data
11 | {
12 | public class BloggerEntities : DbContext
13 | {
14 | public BloggerEntities()
15 | : base("BloggerEntities")
16 | {
17 | Configuration.ProxyCreationEnabled = false;
18 | }
19 |
20 | public DbSet Blogs { get; set; }
21 | public DbSet Articles { get; set; }
22 |
23 | public virtual void Commit()
24 | {
25 | base.SaveChanges();
26 | }
27 |
28 | protected override void OnModelCreating(DbModelBuilder modelBuilder)
29 | {
30 | modelBuilder.Configurations.Add(new ArticleConfiguration());
31 | modelBuilder.Configurations.Add(new BlogConfiguration());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/BloggerInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using UnitTestingWebAPI.Domain;
8 |
9 | namespace UnitTestingWebAPI.Data
10 | {
11 | public class BloggerInitializer : DropCreateDatabaseIfModelChanges
12 | {
13 | protected override void Seed(BloggerEntities context)
14 | {
15 | GetBlogs().ForEach(b => context.Blogs.Add(b));
16 |
17 | context.Commit();
18 | }
19 |
20 | public static List GetBlogs()
21 | {
22 | List _blogs = new List();
23 |
24 | // Add two Blogs
25 | Blog _chsakellsBlog = new Blog()
26 | {
27 | Name = "chsakell's Blog",
28 | URL = "http://chsakell.com/",
29 | Owner = "Chris Sakellarios",
30 | Articles = GetChsakellsArticles()
31 | };
32 |
33 | Blog _dotNetCodeGeeks = new Blog()
34 | {
35 | Name = "DotNETCodeGeeks",
36 | URL = "dotnetcodegeeks",
37 | Owner = ".NET Code Geeks",
38 | Articles = GetDotNETGeeksArticles()
39 | };
40 |
41 | _blogs.Add(_chsakellsBlog);
42 | _blogs.Add(_dotNetCodeGeeks);
43 |
44 | return _blogs;
45 | }
46 |
47 | public static List GetChsakellsArticles()
48 | {
49 | List _articles = new List();
50 |
51 | Article _oData = new Article()
52 | {
53 | Author = "Chris S.",
54 | Title = "ASP.NET Web API feat. OData",
55 | URL = "http://chsakell.com/2015/04/04/asp-net-web-api-feat-odata/",
56 | Contents = @"OData is an open standard protocol allowing the creation and consumption of queryable
57 | and interoperable RESTful APIs. It was initiated by Microsoft and it’s mostly known to
58 | .NET Developers from WCF Data Services. There are many other server platforms supporting
59 | OData services such as Node.js, PHP, Java and SQL Server Reporting Services. More over,
60 | Web API also supports OData and this post will show you how to integrate those two.."
61 | };
62 |
63 | Article _wcfCustomSecurity= new Article()
64 | {
65 | Author = "Chris S.",
66 | Title = "Secure WCF Services with custom encrypted tokens",
67 | URL = "http://chsakell.com/2014/12/13/secure-wcf-services-with-custom-encrypted-tokens/",
68 | Contents = @"Windows Communication Foundation framework comes with a lot of options out of the box,
69 | concerning the security logic you will apply to your services. Different bindings can be
70 | used for certain kind and levels of security. Even the BasicHttpBinding binding supports
71 | some types of security. There are some times though where you cannot or don’t want to use
72 | WCF security available options and hence, you need to develop your own authentication logic
73 | accoarding to your business needs."
74 | };
75 |
76 | _articles.Add(_oData);
77 | _articles.Add(_wcfCustomSecurity);
78 |
79 | return _articles;
80 | }
81 |
82 | public static List GetDotNETGeeksArticles()
83 | {
84 | List _articles = new List();
85 |
86 | Article _angularFeatWebAPI = new Article()
87 | {
88 | Author = "Gordon Beeming",
89 | Title = "AngularJS feat. Web API",
90 | URL = "http://www.dotnetcodegeeks.com/2015/05/angularjs-feat-web-api.html",
91 | Contents = @"Developing Web applications using AngularJS and Web API can be quite amuzing. You can pick
92 | this architecture in case you have in mind a web application with limitted page refreshes or
93 | post backs to the server while each application’s View is based on partial data retrieved from it."
94 | };
95 |
96 | _articles.Add(_angularFeatWebAPI);
97 |
98 | return _articles;
99 | }
100 |
101 | public static List GetAllArticles()
102 | {
103 | List _articles = new List();
104 | _articles.AddRange(GetChsakellsArticles());
105 | _articles.AddRange(GetDotNETGeeksArticles());
106 |
107 | return _articles;
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Configurations/ArticleConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity.ModelConfiguration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using UnitTestingWebAPI.Domain;
8 |
9 | namespace UnitTestingWebAPI.Data.Configurations
10 | {
11 | public class ArticleConfiguration : EntityTypeConfiguration
12 | {
13 | public ArticleConfiguration()
14 | {
15 | ToTable("Article");
16 | Property(a => a.Title).IsRequired().HasMaxLength(100);
17 | Property(a => a.Contents).IsRequired();
18 | Property(a => a.Author).IsRequired().HasMaxLength(50);
19 | Property(a => a.URL).IsRequired().HasMaxLength(200);
20 | Property(a => a.DateCreated).HasColumnType("datetime2");
21 | Property(a => a.DateEdited).HasColumnType("datetime2");
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Configurations/BlogConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity.ModelConfiguration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using UnitTestingWebAPI.Domain;
8 |
9 | namespace UnitTestingWebAPI.Data.Configurations
10 | {
11 | public class BlogConfiguration : EntityTypeConfiguration
12 | {
13 | public BlogConfiguration()
14 | {
15 | ToTable("Blog");
16 | Property(b => b.Name).IsRequired().HasMaxLength(100);
17 | Property(b => b.URL).IsRequired().HasMaxLength(200);
18 | Property(b => b.Owner).IsRequired().HasMaxLength(50);
19 | Property(b => b.DateCreated).HasColumnType("datetime2");
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/DbFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Data.Infrastructure
8 | {
9 | public class DbFactory : Disposable, IDbFactory
10 | {
11 | BloggerEntities dbContext;
12 |
13 | public BloggerEntities Init()
14 | {
15 | return dbContext ?? (dbContext = new BloggerEntities());
16 | }
17 |
18 | protected override void DisposeCore()
19 | {
20 | if (dbContext != null)
21 | dbContext.Dispose();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/Disposable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Data.Infrastructure
8 | {
9 | public class Disposable : IDisposable
10 | {
11 | private bool isDisposed;
12 |
13 | ~Disposable()
14 | {
15 | Dispose(false);
16 | }
17 |
18 | public void Dispose()
19 | {
20 | Dispose(true);
21 | GC.SuppressFinalize(this);
22 | }
23 | private void Dispose(bool disposing)
24 | {
25 | if (!isDisposed && disposing)
26 | {
27 | DisposeCore();
28 | }
29 |
30 | isDisposed = true;
31 | }
32 |
33 | // Ovveride this to dispose custom objects
34 | protected virtual void DisposeCore()
35 | {
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/IDbFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Data.Infrastructure
8 | {
9 | public interface IDbFactory : IDisposable
10 | {
11 | BloggerEntities Init();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/IRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace UnitTestingWebAPI.Data.Infrastructure
9 | {
10 | public interface IRepository where T : class
11 | {
12 | // Marks an entity as new
13 | void Add(T entity);
14 | // Marks an entity as modified
15 | void Update(T entity);
16 | // Marks an entity to be removed
17 | void Delete(T entity);
18 | void Delete(Expression> where);
19 | // Get an entity by int id
20 | T GetById(int id);
21 | // Get an entity using delegate
22 | T Get(Expression> where);
23 | // Gets all entities of type T
24 | IEnumerable GetAll();
25 | // Gets entities using delegate
26 | IEnumerable GetMany(Expression> where);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/IUnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Data.Infrastructure
8 | {
9 | public interface IUnitOfWork
10 | {
11 | void Commit();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/RepositoryBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Linq;
5 | using System.Linq.Expressions;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace UnitTestingWebAPI.Data.Infrastructure
10 | {
11 | public abstract class RepositoryBase where T : class
12 | {
13 | #region Properties
14 | private BloggerEntities dataContext;
15 | private readonly IDbSet dbSet;
16 |
17 | protected IDbFactory DbFactory
18 | {
19 | get;
20 | private set;
21 | }
22 |
23 | protected BloggerEntities DbContext
24 | {
25 | get { return dataContext ?? (dataContext = DbFactory.Init()); }
26 | }
27 | #endregion
28 |
29 | protected RepositoryBase(IDbFactory dbFactory)
30 | {
31 | DbFactory = dbFactory;
32 | dbSet = DbContext.Set();
33 | }
34 |
35 | #region Implementation
36 | public virtual void Add(T entity)
37 | {
38 | dbSet.Add(entity);
39 | }
40 |
41 | public virtual void Update(T entity)
42 | {
43 | dbSet.Attach(entity);
44 | dataContext.Entry(entity).State = EntityState.Modified;
45 | }
46 |
47 | public virtual void Delete(T entity)
48 | {
49 | dbSet.Remove(entity);
50 | }
51 |
52 | public virtual void Delete(Expression> where)
53 | {
54 | IEnumerable objects = dbSet.Where(where).AsEnumerable();
55 | foreach (T obj in objects)
56 | dbSet.Remove(obj);
57 | }
58 |
59 | public virtual T GetById(int id)
60 | {
61 | return dbSet.Find(id);
62 | }
63 |
64 | public virtual IEnumerable GetAll()
65 | {
66 | return dbSet.ToList();
67 | }
68 |
69 | public virtual IEnumerable GetMany(Expression> where)
70 | {
71 | return dbSet.Where(where).ToList();
72 | }
73 |
74 | public T Get(Expression> where)
75 | {
76 | return dbSet.Where(where).FirstOrDefault();
77 | }
78 |
79 | #endregion
80 |
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Infrastructure/UnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Data.Infrastructure
8 | {
9 | public class UnitOfWork : IUnitOfWork
10 | {
11 | private readonly IDbFactory dbFactory;
12 | private BloggerEntities dbContext;
13 |
14 | public UnitOfWork(IDbFactory dbFactory)
15 | {
16 | this.dbFactory = dbFactory;
17 | }
18 |
19 | public BloggerEntities DbContext
20 | {
21 | get { return dbContext ?? (dbContext = dbFactory.Init()); }
22 | }
23 |
24 | public void Commit()
25 | {
26 | DbContext.Commit();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UnitTestingWebAPI.Data")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UnitTestingWebAPI.Data")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a24500b5-c90e-4c6e-a7fb-1af1b513b1d3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Repositories/ArticleRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using UnitTestingWebAPI.Data.Infrastructure;
7 | using UnitTestingWebAPI.Domain;
8 |
9 | namespace UnitTestingWebAPI.Data.Repositories
10 | {
11 | public class ArticleRepository : RepositoryBase, IArticleRepository
12 | {
13 | public ArticleRepository(IDbFactory dbFactory)
14 | : base(dbFactory) { }
15 |
16 | public Article GetArticleByTitle(string articleTitle)
17 | {
18 | var _article = this.DbContext.Articles.Where(b => b.Title == articleTitle).FirstOrDefault();
19 |
20 | return _article;
21 | }
22 | }
23 |
24 | public interface IArticleRepository : IRepository
25 | {
26 | Article GetArticleByTitle(string articleTitle);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/Repositories/BlogRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using UnitTestingWebAPI.Data.Infrastructure;
7 | using UnitTestingWebAPI.Domain;
8 |
9 | namespace UnitTestingWebAPI.Data.Repositories
10 | {
11 | public class BlogRepository : RepositoryBase, IBlogRepository
12 | {
13 | public BlogRepository(IDbFactory dbFactory)
14 | : base(dbFactory) { }
15 |
16 | public Blog GetBlogByName(string blogName)
17 | {
18 | var _blog = this.DbContext.Blogs.Where(b => b.Name == blogName).FirstOrDefault();
19 |
20 | return _blog;
21 | }
22 | }
23 |
24 | public interface IBlogRepository : IRepository
25 | {
26 | Blog GetBlogByName(string blogName);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/UnitTestingWebAPI.Data.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {D9166D82-BE4E-4664-BBCC-7D31C274CB92}
8 | Library
9 | Properties
10 | UnitTestingWebAPI.Data
11 | UnitTestingWebAPI.Data
12 | v4.5.1
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll
37 |
38 |
39 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | {004555f2-5b29-49d0-98fd-60d57e0de8aa}
69 | UnitTestingWebAPI.Domain
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
82 |
83 |
84 |
85 |
92 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Data/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Domain/Article.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Domain
8 | {
9 | public class Article
10 | {
11 | public int ID { get; set; }
12 | public string Title { get; set; }
13 | public string Contents { get; set; }
14 | public string Author { get; set; }
15 | public string URL { get; set; }
16 | public DateTime DateCreated { get; set; }
17 | public DateTime DateEdited { get; set; }
18 |
19 | public int BlogID { get; set; }
20 | public virtual Blog Blog { get; set; }
21 |
22 | public Article()
23 | {
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Domain/Blog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace UnitTestingWebAPI.Domain
8 | {
9 | public class Blog
10 | {
11 | public int ID { get; set; }
12 | public string Name { get; set; }
13 | public string URL { get; set; }
14 | public string Owner { get; set; }
15 | public DateTime DateCreated { get; set; }
16 | public virtual ICollection Articles { get; set; }
17 |
18 | public Blog()
19 | {
20 | Articles = new HashSet();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Domain/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UnitTestingWebAPI.Domain")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UnitTestingWebAPI.Domain")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("68b444bc-9010-46a4-bb5f-5b1d86df42fc")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Domain/UnitTestingWebAPI.Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {004555F2-5B29-49D0-98FD-60D57E0DE8AA}
8 | Library
9 | Properties
10 | UnitTestingWebAPI.Domain
11 | UnitTestingWebAPI.Domain
12 | v4.5.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
54 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Service/ArticleService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using UnitTestingWebAPI.Data.Infrastructure;
7 | using UnitTestingWebAPI.Data.Repositories;
8 | using UnitTestingWebAPI.Domain;
9 |
10 | namespace UnitTestingWebAPI.Service
11 | {
12 | // operations you want to expose
13 | public interface IArticleService
14 | {
15 | IEnumerable GetArticles(string name = null);
16 | Article GetArticle(int id);
17 | Article GetArticle(string name);
18 | void CreateArticle(Article article);
19 | void UpdateArticle(Article article);
20 | void DeleteArticle(Article article);
21 | void SaveArticle();
22 | }
23 |
24 | public class ArticleService : IArticleService
25 | {
26 | private readonly IArticleRepository articlesRepository;
27 | private readonly IUnitOfWork unitOfWork;
28 |
29 | public ArticleService(IArticleRepository articlesRepository, IUnitOfWork unitOfWork)
30 | {
31 | this.articlesRepository = articlesRepository;
32 | this.unitOfWork = unitOfWork;
33 | }
34 |
35 | #region IArticleService Members
36 |
37 | public IEnumerable GetArticles(string title = null)
38 | {
39 | if (string.IsNullOrEmpty(title))
40 | return articlesRepository.GetAll();
41 | else
42 | return articlesRepository.GetAll().Where(c => c.Title.ToLower().Contains(title.ToLower()));
43 | }
44 |
45 | public Article GetArticle(int id)
46 | {
47 | var article = articlesRepository.GetById(id);
48 | return article;
49 | }
50 |
51 | public Article GetArticle(string title)
52 | {
53 | var article = articlesRepository.GetArticleByTitle(title);
54 | return article;
55 | }
56 |
57 | public void CreateArticle(Article article)
58 | {
59 | articlesRepository.Add(article);
60 | }
61 |
62 | public void UpdateArticle(Article article)
63 | {
64 | articlesRepository.Update(article);
65 | }
66 |
67 | public void DeleteArticle(Article article)
68 | {
69 | articlesRepository.Delete(article);
70 | }
71 |
72 | public void SaveArticle()
73 | {
74 | unitOfWork.Commit();
75 | }
76 |
77 | #endregion
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Service/BlogService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using UnitTestingWebAPI.Data.Infrastructure;
7 | using UnitTestingWebAPI.Data.Repositories;
8 | using UnitTestingWebAPI.Domain;
9 |
10 | namespace UnitTestingWebAPI.Service
11 | {
12 | // operations you want to expose
13 | public interface IBlogService
14 | {
15 | IEnumerable GetBlogs(string name = null);
16 | Blog GetBlog(int id);
17 | Blog GetBlog(string name);
18 | void CreateBlog(Blog blog);
19 | void UpdateBlog(Blog blog);
20 | void SaveBlog();
21 | void DeleteBlog(Blog blog);
22 | }
23 |
24 | public class BlogService : IBlogService
25 | {
26 | private readonly IBlogRepository blogsRepository;
27 | private readonly IUnitOfWork unitOfWork;
28 |
29 | public BlogService(IBlogRepository blogsRepository, IUnitOfWork unitOfWork)
30 | {
31 | this.blogsRepository = blogsRepository;
32 | this.unitOfWork = unitOfWork;
33 | }
34 |
35 | #region IBlogService Members
36 |
37 | public IEnumerable GetBlogs(string name = null)
38 | {
39 | if (string.IsNullOrEmpty(name))
40 | return blogsRepository.GetAll();
41 | else
42 | return blogsRepository.GetAll().Where(c => c.Name == name);
43 | }
44 |
45 | public Blog GetBlog(int id)
46 | {
47 | var blog = blogsRepository.GetById(id);
48 | return blog;
49 | }
50 |
51 | public Blog GetBlog(string name)
52 | {
53 | var blog = blogsRepository.GetBlogByName(name);
54 | return blog;
55 | }
56 |
57 | public void CreateBlog(Blog blog)
58 | {
59 | blogsRepository.Add(blog);
60 | }
61 |
62 | public void UpdateBlog(Blog blog)
63 | {
64 | blogsRepository.Update(blog);
65 | }
66 |
67 | public void DeleteBlog(Blog blog)
68 | {
69 | blogsRepository.Delete(blog);
70 | }
71 |
72 | public void SaveBlog()
73 | {
74 | unitOfWork.Commit();
75 | }
76 |
77 | #endregion
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Service/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UnitTestingWebAPI.Service")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UnitTestingWebAPI.Service")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7f3be8c4-b828-45dc-8386-57505b87e056")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Service/UnitTestingWebAPI.Service.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EA36FD16-A613-4F31-8BFF-94ECE2028A63}
8 | Library
9 | Properties
10 | UnitTestingWebAPI.Service
11 | UnitTestingWebAPI.Service
12 | v4.5.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | {d9166d82-be4e-4664-bbcc-7d31c274cb92}
49 | UnitTestingWebAPI.Data
50 |
51 |
52 | {004555f2-5b29-49d0-98fd-60d57e0de8aa}
53 | UnitTestingWebAPI.Domain
54 |
55 |
56 |
57 |
64 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/ActionFilterTests.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using Microsoft.Owin.Hosting;
3 | using NUnit.Framework;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Net.Http;
8 | using System.Net.Http.Formatting;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Web.Http.Controllers;
12 | using System.Web.Http.Filters;
13 | using UnitTestingWebAPI.API.Core.Filters;
14 | using UnitTestingWebAPI.Data;
15 | using UnitTestingWebAPI.Domain;
16 | using UnitTestingWebAPI.Tests.Hosting;
17 | #endregion
18 |
19 | namespace UnitTestingWebAPI.Tests
20 | {
21 | [TestFixture]
22 | public class ActionFilterTests
23 | {
24 | #region Variables
25 | private List _articles;
26 | #endregion
27 |
28 | #region Setup
29 | [SetUp]
30 | public void Setup()
31 | {
32 | _articles = BloggerInitializer.GetAllArticles();
33 | }
34 | #endregion
35 |
36 | #region Tests
37 | [Test]
38 | public void ShouldSortArticlesByTitle()
39 | {
40 | var filter = new ArticlesReversedFilter();
41 | var executedContext = new HttpActionExecutedContext(new HttpActionContext
42 | {
43 | Response = new HttpResponseMessage(),
44 | }, null);
45 |
46 | executedContext.Response.Content = new ObjectContent>(new List(_articles), new JsonMediaTypeFormatter());
47 |
48 | filter.OnActionExecuted(executedContext);
49 |
50 | var _returnedArticles = executedContext.Response.Content.ReadAsAsync>().Result;
51 |
52 | Assert.That(_returnedArticles.First(), Is.EqualTo(_articles.Last()));
53 | }
54 |
55 | [Test]
56 | public void ShouldCallToControllerActionReverseArticles()
57 | {
58 | //Arrange
59 | var address = "http://localhost:9000/";
60 |
61 | using (WebApp.Start(address))
62 | {
63 | HttpClient _client = new HttpClient();
64 | var response = _client.GetAsync(address + "api/articles").Result;
65 |
66 | var _returnedArticles = response.Content.ReadAsAsync>().Result;
67 |
68 | Assert.That(_returnedArticles.First().Title, Is.EqualTo(BloggerInitializer.GetAllArticles().Last().Title));
69 | }
70 | }
71 | #endregion
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/ControllerTests.cs:
--------------------------------------------------------------------------------
1 | #region Usings
2 | using Moq;
3 | using NUnit.Framework;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Net.Http;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Web.Http;
12 | using System.Web.Http.Results;
13 | using System.Web.Http.Routing;
14 | using UnitTestingWebAPI.API.Core.Controllers;
15 | using UnitTestingWebAPI.Data;
16 | using UnitTestingWebAPI.Data.Infrastructure;
17 | using UnitTestingWebAPI.Data.Repositories;
18 | using UnitTestingWebAPI.Domain;
19 | using UnitTestingWebAPI.Service;
20 | #endregion
21 |
22 | namespace UnitTestingWebAPI.Tests
23 | {
24 | [TestFixture]
25 | public class ControllerTests
26 | {
27 | #region Variables
28 | IArticleService _articleService;
29 | IArticleRepository _articleRepository;
30 | IUnitOfWork _unitOfWork;
31 | List _randomArticles;
32 | #endregion
33 |
34 | #region Setup
35 | [SetUp]
36 | public void Setup()
37 | {
38 | _randomArticles = SetupArticles();
39 |
40 | _articleRepository = SetupArticleRepository();
41 | _unitOfWork = new Mock().Object;
42 | _articleService = new ArticleService(_articleRepository, _unitOfWork);
43 | }
44 |
45 | public List SetupArticles()
46 | {
47 | int _counter = new int();
48 | List _articles = BloggerInitializer.GetAllArticles();
49 |
50 | foreach (Article _article in _articles)
51 | _article.ID = ++_counter;
52 |
53 | return _articles;
54 | }
55 |
56 | public IArticleRepository SetupArticleRepository()
57 | {
58 | // Init repository
59 | var repo = new Mock();
60 |
61 | // Setup mocking behavior
62 | repo.Setup(r => r.GetAll()).Returns(_randomArticles);
63 |
64 | repo.Setup(r => r.GetById(It.IsAny()))
65 | .Returns(new Func(
66 | id => _randomArticles.Find(a => a.ID.Equals(id))));
67 |
68 | repo.Setup(r => r.Add(It.IsAny()))
69 | .Callback(new Action(newArticle =>
70 | {
71 | dynamic maxArticleID = _randomArticles.Last().ID;
72 | dynamic nextArticleID = maxArticleID + 1;
73 | newArticle.ID = nextArticleID;
74 | newArticle.DateCreated = DateTime.Now;
75 | _randomArticles.Add(newArticle);
76 | }));
77 |
78 | repo.Setup(r => r.Update(It.IsAny()))
79 | .Callback(new Action(x =>
80 | {
81 | var oldArticle = _randomArticles.Find(a => a.ID == x.ID);
82 | oldArticle.DateEdited = DateTime.Now;
83 | oldArticle.URL = x.URL;
84 | oldArticle.Title = x.Title;
85 | oldArticle.Contents = x.Contents;
86 | oldArticle.BlogID = x.BlogID;
87 | }));
88 |
89 | repo.Setup(r => r.Delete(It.IsAny()))
90 | .Callback(new Action(x =>
91 | {
92 | var _articleToRemove = _randomArticles.Find(a => a.ID == x.ID);
93 |
94 | if (_articleToRemove != null)
95 | _randomArticles.Remove(_articleToRemove);
96 | }));
97 |
98 | // Return mock implementation
99 | return repo.Object;
100 | }
101 |
102 | #endregion
103 |
104 | #region Tests
105 |
106 | [Test]
107 | public void ControlerShouldReturnAllArticles()
108 | {
109 | var _articlesController = new ArticlesController(_articleService);
110 |
111 | var result = _articlesController.GetArticles();
112 |
113 | CollectionAssert.AreEqual(result, _randomArticles);
114 | }
115 |
116 | [Test]
117 | public void ControlerShouldReturnLastArticle()
118 | {
119 | var _articlesController = new ArticlesController(_articleService);
120 |
121 | var result = _articlesController.GetArticle(3) as OkNegotiatedContentResult;
122 |
123 | Assert.IsNotNull(result);
124 | Assert.AreEqual(result.Content.Title, _randomArticles.Last().Title);
125 | }
126 |
127 | [Test]
128 | public void ControlerShouldPutReturnBadRequestResult()
129 | {
130 | var _articlesController = new ArticlesController(_articleService)
131 | {
132 | Configuration = new HttpConfiguration(),
133 | Request = new HttpRequestMessage
134 | {
135 | Method = HttpMethod.Put,
136 | RequestUri = new Uri("http://localhost/api/articles/-1")
137 | }
138 | };
139 |
140 | var badresult = _articlesController.PutArticle(-1, new Article() { Title = "Unknown Article" });
141 | Assert.That(badresult, Is.TypeOf());
142 | }
143 |
144 | [Test]
145 | public void ControlerShouldPutUpdateFirstArticle()
146 | {
147 | var _articlesController = new ArticlesController(_articleService)
148 | {
149 | Configuration = new HttpConfiguration(),
150 | Request = new HttpRequestMessage
151 | {
152 | Method = HttpMethod.Put,
153 | RequestUri = new Uri("http://localhost/api/articles/1")
154 | }
155 | };
156 |
157 | IHttpActionResult updateResult = _articlesController.PutArticle(1, new Article()
158 | {
159 | ID = 1,
160 | Title = "ASP.NET Web API feat. OData",
161 | URL = "http://t.co/fuIbNoc7Zh",
162 | Contents = @"OData is an open standard protocol.."
163 | }) as IHttpActionResult;
164 |
165 | Assert.That(updateResult, Is.TypeOf());
166 |
167 | StatusCodeResult statusCodeResult = updateResult as StatusCodeResult;
168 |
169 | Assert.That(statusCodeResult.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
170 |
171 | Assert.That(_randomArticles.First().URL, Is.EqualTo("http://t.co/fuIbNoc7Zh"));
172 | }
173 |
174 | [Test]
175 | public void ControlerShouldPostNewArticle()
176 | {
177 | var article = new Article
178 | {
179 | Title = "Web API Unit Testing",
180 | URL = "http://chsakell.com/web-api-unit-testing",
181 | Author = "Chris Sakellarios",
182 | DateCreated = DateTime.Now,
183 | Contents = "Unit testing Web API.."
184 | };
185 |
186 | var _articlesController = new ArticlesController(_articleService)
187 | {
188 | Configuration = new HttpConfiguration(),
189 | Request = new HttpRequestMessage
190 | {
191 | Method = HttpMethod.Post,
192 | RequestUri = new Uri("http://localhost/api/articles")
193 | }
194 | };
195 |
196 | _articlesController.Configuration.MapHttpAttributeRoutes();
197 | _articlesController.Configuration.EnsureInitialized();
198 | _articlesController.RequestContext.RouteData = new HttpRouteData(
199 | new HttpRoute(), new HttpRouteValueDictionary { { "_articlesController", "Articles" } });
200 | var result = _articlesController.PostArticle(article) as CreatedAtRouteNegotiatedContentResult;
201 |
202 | Assert.That(result.RouteName, Is.EqualTo("DefaultApi"));
203 | Assert.That(result.Content.ID, Is.EqualTo(result.RouteValues["id"]));
204 | Assert.That(result.Content.ID, Is.EqualTo(_randomArticles.Max(a => a.ID)));
205 | }
206 |
207 | [Test]
208 | public void ControlerShouldNotPostNewArticle()
209 | {
210 | var article = new Article
211 | {
212 | Title = "Web API Unit Testing",
213 | URL = "http://chsakell.com/web-api-unit-testing",
214 | Author = "Chris Sakellarios",
215 | DateCreated = DateTime.Now,
216 | Contents = null
217 | };
218 |
219 | var _articlesController = new ArticlesController(_articleService)
220 | {
221 | Configuration = new HttpConfiguration(),
222 | Request = new HttpRequestMessage
223 | {
224 | Method = HttpMethod.Post,
225 | RequestUri = new Uri("http://localhost/api/articles")
226 | }
227 | };
228 |
229 | _articlesController.Configuration.MapHttpAttributeRoutes();
230 | _articlesController.Configuration.EnsureInitialized();
231 | _articlesController.RequestContext.RouteData = new HttpRouteData(
232 | new HttpRoute(), new HttpRouteValueDictionary { { "Controller", "Articles" } });
233 | _articlesController.ModelState.AddModelError("Contents", "Contents is required field");
234 |
235 | var result = _articlesController.PostArticle(article) as InvalidModelStateResult;
236 |
237 | Assert.That(result.ModelState.Count, Is.EqualTo(1));
238 | Assert.That(result.ModelState.IsValid, Is.EqualTo(false));
239 | }
240 |
241 | #endregion
242 | }
243 | }
244 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/Helpers/ControllerActionSelector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Web.Http;
9 | using System.Web.Http.Controllers;
10 | using System.Web.Http.Dispatcher;
11 | using System.Web.Http.Hosting;
12 | using System.Web.Http.Routing;
13 |
14 | namespace UnitTestingWebAPI.Tests.Helpers
15 | {
16 | public class ControllerActionSelector
17 | {
18 | #region Variables
19 | HttpConfiguration config;
20 | HttpRequestMessage request;
21 | IHttpRouteData routeData;
22 | IHttpControllerSelector controllerSelector;
23 | HttpControllerContext controllerContext;
24 | #endregion
25 |
26 | #region Constructor
27 | public ControllerActionSelector(HttpConfiguration conf, HttpRequestMessage req)
28 | {
29 | config = conf;
30 | request = req;
31 | routeData = config.Routes.GetRouteData(request);
32 | request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData;
33 | controllerSelector = new DefaultHttpControllerSelector(config);
34 | controllerContext = new HttpControllerContext(config, routeData, request);
35 | }
36 | #endregion
37 |
38 | #region Methods
39 | public string GetActionName()
40 | {
41 | if (controllerContext.ControllerDescriptor == null)
42 | GetControllerType();
43 |
44 | var actionSelector = new ApiControllerActionSelector();
45 | var descriptor = actionSelector.SelectAction(controllerContext);
46 |
47 | return descriptor.ActionName;
48 | }
49 |
50 | public Type GetControllerType()
51 | {
52 | var descriptor = controllerSelector.SelectController(request);
53 | controllerContext.ControllerDescriptor = descriptor;
54 | return descriptor.ControllerType;
55 | }
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/Hosting/Startup.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using Autofac;
3 | using Autofac.Integration.WebApi;
4 | using Moq;
5 | using Owin;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Web.Http;
12 | using System.Web.Http.Dispatcher;
13 | using System.Web.Http.SelfHost;
14 | using UnitTestingWebAPI.API.Core;
15 | using UnitTestingWebAPI.API.Core.Controllers;
16 | using UnitTestingWebAPI.API.Core.Filters;
17 | using UnitTestingWebAPI.API.Core.MessageHandlers;
18 | using UnitTestingWebAPI.Data;
19 | using UnitTestingWebAPI.Data.Infrastructure;
20 | using UnitTestingWebAPI.Data.Repositories;
21 | using UnitTestingWebAPI.Domain;
22 | using UnitTestingWebAPI.Service;
23 | #endregion
24 |
25 | namespace UnitTestingWebAPI.Tests.Hosting
26 | {
27 | public class Startup
28 | {
29 | public void Configuration(IAppBuilder appBuilder)
30 | {
31 | var config = new HttpConfiguration();
32 | config.MessageHandlers.Add(new HeaderAppenderHandler());
33 | config.MessageHandlers.Add(new EndRequestHandler());
34 | config.Filters.Add(new ArticlesReversedFilter());
35 | config.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());
36 |
37 | config.Routes.MapHttpRoute(
38 | name: "DefaultApi",
39 | routeTemplate: "api/{controller}/{id}",
40 | defaults: new { id = RouteParameter.Optional }
41 | );
42 | config.MapHttpAttributeRoutes();
43 |
44 | // Autofac configuration
45 | var builder = new ContainerBuilder();
46 | builder.RegisterApiControllers(typeof(ArticlesController).Assembly);
47 |
48 | // Unit of Work
49 | var _unitOfWork = new Mock();
50 | builder.RegisterInstance(_unitOfWork.Object).As();
51 |
52 | //Repositories
53 | var _articlesRepository = new Mock();
54 | _articlesRepository.Setup(x => x.GetAll()).Returns(
55 | BloggerInitializer.GetAllArticles()
56 | );
57 | builder.RegisterInstance(_articlesRepository.Object).As();
58 |
59 | var _blogsRepository = new Mock();
60 | _blogsRepository.Setup(x => x.GetAll()).Returns(
61 | BloggerInitializer.GetBlogs
62 | );
63 | builder.RegisterInstance(_blogsRepository.Object).As();
64 |
65 | // Services
66 | builder.RegisterAssemblyTypes(typeof(ArticleService).Assembly)
67 | .Where(t => t.Name.EndsWith("Service"))
68 | .AsImplementedInterfaces().InstancePerRequest();
69 |
70 | builder.RegisterInstance(new ArticleService(_articlesRepository.Object, _unitOfWork.Object));
71 | builder.RegisterInstance(new BlogService(_blogsRepository.Object, _unitOfWork.Object));
72 |
73 | IContainer container = builder.Build();
74 | config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
75 |
76 | appBuilder.UseWebApi(config);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/MediaTypeFormatterTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net.Http;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using UnitTestingWebAPI.API.Core.MediaTypeFormatters;
9 | using UnitTestingWebAPI.Data;
10 | using UnitTestingWebAPI.Domain;
11 |
12 | namespace UnitTestingWebAPI.Tests
13 | {
14 | [TestFixture]
15 | public class MediaTypeFormatterTests
16 | {
17 | #region Variables
18 | Blog _blog;
19 | Article _article;
20 | ArticleFormatter _formatter;
21 | #endregion
22 |
23 | #region Setup
24 | [SetUp]
25 | public void Setup()
26 | {
27 | _blog = BloggerInitializer.GetBlogs().First();
28 | _article = BloggerInitializer.GetChsakellsArticles().First();
29 | _formatter = new ArticleFormatter();
30 | }
31 | #endregion
32 |
33 | #region Tests
34 | [Test]
35 | public void FormatterShouldThrowExceptionWhenUnsupportedType()
36 | {
37 | Assert.Throws(() => new ObjectContent(_blog, _formatter));
38 | }
39 |
40 | [Test]
41 | public void FormatterShouldNotThrowExceptionWhenArticle()
42 | {
43 | Assert.DoesNotThrow(() => new ObjectContent(_article, _formatter));
44 | }
45 |
46 | [Test]
47 | public void FormatterShouldHeaderBeSetCorrectly()
48 | {
49 | var content = new ObjectContent(_article, new ArticleFormatter());
50 |
51 | Assert.That(content.Headers.ContentType.MediaType, Is.EqualTo("application/article"));
52 | }
53 |
54 | [Test]
55 | public async void FormatterShouldBeAbleToDeserializeArticle()
56 | {
57 | var content = new ObjectContent(_article, _formatter);
58 |
59 | var deserializedItem = await content.ReadAsAsync(new[] { _formatter });
60 |
61 | Assert.That(_article, Is.SameAs(deserializedItem));
62 | }
63 |
64 | [Test]
65 | public void FormatterShouldNotBeAbleToWriteUnsupportedType()
66 | {
67 | var canWriteBlog = _formatter.CanWriteType(typeof(Blog));
68 | Assert.That(canWriteBlog, Is.False);
69 | }
70 |
71 | [Test]
72 | public void FormatterShouldBeAbleToWriteArticle()
73 | {
74 | var canWriteArticle = _formatter.CanWriteType(typeof(Article));
75 | Assert.That(canWriteArticle, Is.True);
76 | }
77 | #endregion
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/MessageHandlerTests.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using Microsoft.Owin.Hosting;
3 | using Moq;
4 | using NUnit.Framework;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Net.Http;
9 | using System.Text;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 | using System.Web.Http;
13 | using UnitTestingWebAPI.API.Core.Controllers;
14 | using UnitTestingWebAPI.API.Core.MessageHandlers;
15 | using UnitTestingWebAPI.Data;
16 | using UnitTestingWebAPI.Data.Infrastructure;
17 | using UnitTestingWebAPI.Data.Repositories;
18 | using UnitTestingWebAPI.Domain;
19 | using UnitTestingWebAPI.Service;
20 | using UnitTestingWebAPI.Tests.Hosting;
21 | #endregion
22 |
23 | namespace UnitTestingWebAPI.Tests
24 | {
25 | [TestFixture]
26 | public class MessageHandlerTests
27 | {
28 | #region Variables
29 | private EndRequestHandler _endRequestHandler;
30 | private HeaderAppenderHandler _headerAppenderHandler;
31 | #endregion
32 |
33 | #region Setup
34 | [SetUp]
35 | public void Setup()
36 | {
37 | // Direct MessageHandler test
38 | _endRequestHandler = new EndRequestHandler();
39 | _headerAppenderHandler = new HeaderAppenderHandler()
40 | {
41 | InnerHandler = _endRequestHandler
42 | };
43 | }
44 | #endregion
45 |
46 | #region Tests
47 | [Test]
48 | public async void ShouldAppendCustomHeader()
49 | {
50 | var invoker = new HttpMessageInvoker(_headerAppenderHandler);
51 | var result = await invoker.SendAsync(new HttpRequestMessage(HttpMethod.Get,
52 | new Uri("http://localhost/api/test/")), CancellationToken.None);
53 |
54 | Assert.That(result.Headers.Contains("X-WebAPI-Header"), Is.True);
55 | Assert.That(result.Content.ReadAsStringAsync().Result,
56 | Is.EqualTo("Unit testing message handlers!"));
57 | }
58 |
59 | [Test]
60 | public void ShouldCallToControllerActionAppendCustomHeader()
61 | {
62 | //Arrange
63 | var address = "http://localhost:9000/";
64 |
65 | using (WebApp.Start(address))
66 | {
67 | HttpClient _client = new HttpClient();
68 | var response = _client.GetAsync(address + "api/articles").Result;
69 |
70 | Assert.That(response.Headers.Contains("X-WebAPI-Header"), Is.True);
71 |
72 | var _returnedArticles = response.Content.ReadAsAsync>().Result;
73 | Assert.That(_returnedArticles.Count, Is.EqualTo( BloggerInitializer.GetAllArticles().Count));
74 | }
75 | }
76 | #endregion
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UnitTestingWebAPI.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UnitTestingWebAPI.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("0d2b4c59-fefa-4fdd-b4d6-0a94721c94b1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/RouteTests.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using NUnit.Framework;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Linq.Expressions;
7 | using System.Net.Http;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Web.Http;
11 | using UnitTestingWebAPI.API.Core.Controllers;
12 | using UnitTestingWebAPI.Domain;
13 | using UnitTestingWebAPI.Tests.Helpers;
14 | #endregion
15 |
16 | namespace UnitTestingWebAPI.Tests
17 | {
18 | [TestFixture]
19 | public class RouteTests
20 | {
21 | #region Variables
22 | HttpConfiguration _config;
23 | #endregion
24 |
25 | #region Setup
26 | [SetUp]
27 | public void Setup()
28 | {
29 | _config = new HttpConfiguration();
30 | _config.Routes.MapHttpRoute(name: "DefaultWebAPI", routeTemplate: "api/{controller}/{id}",
31 | defaults: new { id = RouteParameter.Optional });
32 | }
33 | #endregion
34 |
35 | #region Tests
36 | [Test]
37 | public void RouteShouldControllerGetArticleIsInvoked()
38 | {
39 | var request = new HttpRequestMessage(HttpMethod.Get, "http://www.chsakell.com/api/articles/5");
40 |
41 | var _actionSelector = new ControllerActionSelector(_config, request);
42 |
43 | Assert.That(typeof(ArticlesController), Is.EqualTo(_actionSelector.GetControllerType()));
44 | Assert.That(GetMethodName((ArticlesController c) => c.GetArticle(5)),
45 | Is.EqualTo(_actionSelector.GetActionName()));
46 | }
47 |
48 | [Test]
49 | public void RouteShouldPostArticleActionIsInvoked()
50 | {
51 | var request = new HttpRequestMessage(HttpMethod.Post, "http://www.chsakell.com/api/articles/");
52 |
53 | var _actionSelector = new ControllerActionSelector(_config, request);
54 |
55 | Assert.That(GetMethodName((ArticlesController c) =>
56 | c.PostArticle(new Article())), Is.EqualTo(_actionSelector.GetActionName()));
57 | }
58 |
59 | [Test]
60 | public void RouteShouldInvalidRouteThrowException()
61 | {
62 | var request = new HttpRequestMessage(HttpMethod.Post, "http://www.chsakell.com/api/InvalidController/");
63 |
64 | var _actionSelector = new ControllerActionSelector(_config, request);
65 |
66 | Assert.Throws(() => _actionSelector.GetActionName());
67 | }
68 |
69 | #endregion
70 |
71 | #region Helper methods
72 | public static string GetMethodName(Expression> expression)
73 | {
74 | var method = expression.Body as MethodCallExpression;
75 | if (method != null)
76 | return method.Method.Name;
77 |
78 | throw new ArgumentException("Expression is wrong");
79 | }
80 | #endregion
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/ServicesTests.cs:
--------------------------------------------------------------------------------
1 | #region Using
2 | using Moq;
3 | using NUnit.Framework;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using UnitTestingWebAPI.Data;
10 | using UnitTestingWebAPI.Data.Infrastructure;
11 | using UnitTestingWebAPI.Data.Repositories;
12 | using UnitTestingWebAPI.Domain;
13 | using UnitTestingWebAPI.Service;
14 | #endregion
15 |
16 | namespace UnitTestingWebAPI.Tests
17 | {
18 | [TestFixture]
19 | public class ServicesTests
20 | {
21 | #region Variables
22 | IArticleService _articleService;
23 | IArticleRepository _articleRepository;
24 | IUnitOfWork _unitOfWork;
25 | List _randomArticles;
26 | #endregion
27 |
28 | #region Setup
29 | [SetUp]
30 | public void Setup()
31 | {
32 | _randomArticles = SetupArticles();
33 |
34 | _articleRepository = SetupArticleRepository();
35 | _unitOfWork = new Mock().Object;
36 | _articleService = new ArticleService(_articleRepository, _unitOfWork);
37 | }
38 |
39 | public List SetupArticles()
40 | {
41 | int _counter = new int();
42 | List _articles = BloggerInitializer.GetAllArticles();
43 |
44 | foreach (Article _article in _articles)
45 | _article.ID = ++_counter;
46 |
47 | return _articles;
48 | }
49 |
50 | public IArticleRepository SetupArticleRepository()
51 | {
52 | // Init repository
53 | var repo = new Mock();
54 |
55 | // Setup mocking behavior
56 | repo.Setup(r => r.GetAll()).Returns(_randomArticles);
57 |
58 | repo.Setup(r => r.GetById(It.IsAny()))
59 | .Returns(new Func(
60 | id => _randomArticles.Find(a => a.ID.Equals(id))));
61 |
62 | repo.Setup(r => r.Add(It.IsAny()))
63 | .Callback(new Action(newArticle =>
64 | {
65 | dynamic maxArticleID = _randomArticles.Last().ID;
66 | dynamic nextArticleID = maxArticleID + 1;
67 | newArticle.ID = nextArticleID;
68 | newArticle.DateCreated = DateTime.Now;
69 | _randomArticles.Add(newArticle);
70 | }));
71 |
72 | repo.Setup(r => r.Update(It.IsAny()))
73 | .Callback(new Action(x =>
74 | {
75 | var oldArticle = _randomArticles.Find(a => a.ID == x.ID);
76 | oldArticle.DateEdited = DateTime.Now;
77 | oldArticle = x;
78 | }));
79 |
80 | repo.Setup(r => r.Delete(It.IsAny()))
81 | .Callback(new Action(x =>
82 | {
83 | var _articleToRemove = _randomArticles.Find(a => a.ID == x.ID);
84 |
85 | if (_articleToRemove != null)
86 | _randomArticles.Remove(_articleToRemove);
87 | }));
88 |
89 | // Return mock implementation
90 | return repo.Object;
91 | }
92 |
93 | #endregion
94 |
95 | #region Tests
96 | [Test]
97 | public void ServiceShouldReturnAllArticles()
98 | {
99 | var articles = _articleService.GetArticles();
100 |
101 | Assert.That(articles, Is.EqualTo(_randomArticles));
102 | }
103 |
104 | [Test]
105 | public void ServiceShouldReturnRightArticle()
106 | {
107 | var wcfSecurityArticle = _articleService.GetArticle(2);
108 |
109 | Assert.That(wcfSecurityArticle,
110 | Is.EqualTo(_randomArticles.Find(a => a.Title.Contains("Secure WCF Services"))));
111 | }
112 |
113 | [Test]
114 | public void ServiceShouldAddNewArticle()
115 | {
116 | var _newArticle = new Article()
117 | {
118 | Author = "Chris Sakellarios",
119 | Contents = "If you are an ASP.NET MVC developer, you will certainly..",
120 | Title = "URL Rooting in ASP.NET (Web Forms)",
121 | URL = "http://chsakell.com/2013/12/15/url-rooting-in-asp-net-web-forms/"
122 | };
123 |
124 | int _maxArticleIDBeforeAdd = _randomArticles.Max(a => a.ID);
125 | _articleService.CreateArticle(_newArticle);
126 |
127 | Assert.That(_newArticle, Is.EqualTo(_randomArticles.Last()));
128 | Assert.That(_maxArticleIDBeforeAdd + 1, Is.EqualTo(_randomArticles.Last().ID));
129 | }
130 |
131 | [Test]
132 | public void ServiceShouldUpdateArticle()
133 | {
134 | var _firstArticle = _randomArticles.First();
135 |
136 | _firstArticle.Title = "OData feat. ASP.NET Web API"; // reversed :-)
137 | _firstArticle.URL = "http://t.co/fuIbNoc7Zh"; // short link
138 | _articleService.UpdateArticle(_firstArticle);
139 |
140 | Assert.That(_firstArticle.DateEdited, Is.Not.EqualTo(DateTime.MinValue));
141 | Assert.That(_firstArticle.URL, Is.EqualTo("http://t.co/fuIbNoc7Zh"));
142 | Assert.That(_firstArticle.ID, Is.EqualTo(1)); // hasn't changed
143 | }
144 |
145 | [Test]
146 | public void ServiceShouldDeleteArticle()
147 | {
148 | int maxID = _randomArticles.Max(a => a.ID); // Before removal
149 | var _lastArticle = _randomArticles.Last();
150 |
151 | // Remove last article
152 | _articleService.DeleteArticle(_lastArticle);
153 |
154 | Assert.That(maxID, Is.GreaterThan(_randomArticles.Max(a => a.ID))); // Max reduced by 1
155 | }
156 |
157 | #endregion
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/UnitTestingWebAPI.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6A2CCFCC-5497-45B7-9C37-E944147817B9}
8 | Library
9 | Properties
10 | UnitTestingWebAPI.Tests
11 | UnitTestingWebAPI.Tests
12 | v4.5.1
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\Autofac.3.5.0\lib\net40\Autofac.dll
37 |
38 |
39 | ..\packages\Autofac.WebApi2.3.4.0\lib\net45\Autofac.Integration.WebApi.dll
40 |
41 |
42 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll
43 |
44 |
45 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll
46 |
47 |
48 | ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
49 |
50 |
51 | ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll
52 |
53 |
54 | ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll
55 |
56 |
57 | ..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll
58 |
59 |
60 | False
61 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
62 |
63 |
64 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll
65 |
66 |
67 | ..\packages\Owin.1.0\lib\net40\Owin.dll
68 |
69 |
70 |
71 |
72 |
73 |
74 | False
75 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
76 |
77 |
78 | False
79 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
80 |
81 |
82 | ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
83 |
84 |
85 | False
86 | ..\packages\Microsoft.AspNet.WebApi.SelfHost.5.2.3\lib\net45\System.Web.Http.SelfHost.dll
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | {04d7ae21-cabb-44a5-882c-44890aa19092}
108 | UnitTestingWebAPI.API.Core
109 |
110 |
111 | {d9166d82-be4e-4664-bbcc-7d31c274cb92}
112 | UnitTestingWebAPI.Data
113 |
114 |
115 | {004555f2-5b29-49d0-98fd-60d57e0de8aa}
116 | UnitTestingWebAPI.Domain
117 |
118 |
119 | {ea36fd16-a613-4f31-8bff-94ece2028a63}
120 | UnitTestingWebAPI.Service
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
135 |
136 |
137 |
138 |
145 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/UnitTestingWebAPI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestingWebAPI.Domain", "UnitTestingWebAPI.Domain\UnitTestingWebAPI.Domain.csproj", "{004555F2-5B29-49D0-98FD-60D57E0DE8AA}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestingWebAPI.Data", "UnitTestingWebAPI.Data\UnitTestingWebAPI.Data.csproj", "{D9166D82-BE4E-4664-BBCC-7D31C274CB92}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestingWebAPI.Service", "UnitTestingWebAPI.Service\UnitTestingWebAPI.Service.csproj", "{EA36FD16-A613-4F31-8BFF-94ECE2028A63}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestingWebAPI.API.Core", "UnitTestingWebAPI.API.Core\UnitTestingWebAPI.API.Core.csproj", "{04D7AE21-CABB-44A5-882C-44890AA19092}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestingWebAPI.API", "UnitTestingWebAPI.API\UnitTestingWebAPI.API.csproj", "{6D9E0639-885F-4B25-A5C4-1BEA8CF2F8C4}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestingWebAPI.Tests", "UnitTestingWebAPI.Tests\UnitTestingWebAPI.Tests.csproj", "{6A2CCFCC-5497-45B7-9C37-E944147817B9}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{7C5C5B36-EDA0-462C-87E8-9C70145078BD}"
19 | ProjectSection(SolutionItems) = preProject
20 | .nuget\NuGet.Config = .nuget\NuGet.Config
21 | .nuget\NuGet.exe = .nuget\NuGet.exe
22 | .nuget\NuGet.targets = .nuget\NuGet.targets
23 | EndProjectSection
24 | EndProject
25 | Global
26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
27 | Debug|Any CPU = Debug|Any CPU
28 | Release|Any CPU = Release|Any CPU
29 | EndGlobalSection
30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
31 | {004555F2-5B29-49D0-98FD-60D57E0DE8AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {004555F2-5B29-49D0-98FD-60D57E0DE8AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {004555F2-5B29-49D0-98FD-60D57E0DE8AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {004555F2-5B29-49D0-98FD-60D57E0DE8AA}.Release|Any CPU.Build.0 = Release|Any CPU
35 | {D9166D82-BE4E-4664-BBCC-7D31C274CB92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {D9166D82-BE4E-4664-BBCC-7D31C274CB92}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {D9166D82-BE4E-4664-BBCC-7D31C274CB92}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {D9166D82-BE4E-4664-BBCC-7D31C274CB92}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {EA36FD16-A613-4F31-8BFF-94ECE2028A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {EA36FD16-A613-4F31-8BFF-94ECE2028A63}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {EA36FD16-A613-4F31-8BFF-94ECE2028A63}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {EA36FD16-A613-4F31-8BFF-94ECE2028A63}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {04D7AE21-CABB-44A5-882C-44890AA19092}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {04D7AE21-CABB-44A5-882C-44890AA19092}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {04D7AE21-CABB-44A5-882C-44890AA19092}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {04D7AE21-CABB-44A5-882C-44890AA19092}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {6D9E0639-885F-4B25-A5C4-1BEA8CF2F8C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {6D9E0639-885F-4B25-A5C4-1BEA8CF2F8C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {6D9E0639-885F-4B25-A5C4-1BEA8CF2F8C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {6D9E0639-885F-4B25-A5C4-1BEA8CF2F8C4}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {6A2CCFCC-5497-45B7-9C37-E944147817B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {6A2CCFCC-5497-45B7-9C37-E944147817B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {6A2CCFCC-5497-45B7-9C37-E944147817B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {6A2CCFCC-5497-45B7-9C37-E944147817B9}.Release|Any CPU.Build.0 = Release|Any CPU
55 | EndGlobalSection
56 | GlobalSection(SolutionProperties) = preSolution
57 | HideSolutionNode = FALSE
58 | EndGlobalSection
59 | EndGlobal
60 |
--------------------------------------------------------------------------------
/licence:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 chsakell
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------