Unit testing of the Services Telerik Software Academy Web Services and Cloud.

Slides:



Advertisements
Similar presentations
@ScotHillier Web Parts Workflows Pages Libraries App Parts SharePoint-Hosted Apps Provider-Hosted Apps.
Advertisements

INTRODUCTION TO ASP.NET MVC AND EXAMPLE WALKTHROUGH RAJAT ARYA EFECS - OIM DAWG – 4/21/2009 ASP.NET MVC.
Computer Monitoring System for EE Faculty By Yaroslav Ross And Denis Zakrevsky Supervisor: Viktor Kulikov.
Computer Science 101 Web Access to Databases Overview of Web Access to Databases.
Nikolay Kostov Telerik Software Academy academy.telerik.com Senior Software Developer and Technical Trainer
Classical OOP in JavaScript Classes and stuff Telerik Software Academy
Ruby on Rails. What is Ruby on Rails? Ruby on Rails is an open source full-stack web framework. It is an alternative to PHP/MySQL. It can render templates,
Kay Herzam Herzam IT Consulting What‘s new in ASP.NET MS TechTalk.
M. Taimoor Khan * Java Server Pages (JSP) is a server-side programming technology that enables the creation of dynamic,
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Kuali Rice at Indiana University Rice Setup Options July 29-30, 2008 Eric Westfall.
Server-side Scripting Powering the webs favourite services.
BIT 286: Web Applications Lecture 04 : Thursday, January 15, 2015 ASP.Net MVC - Models.
CSC 213 – Large Scale Programming. Why Do We Test?
ASP.NET Web API Udaiappa Ramachandran NHDN-Nashua.NET/Cloud Computing UG Lead Blog:
Getting Started with the ASP.NET Web API Dhananjay Kumar Infragistics Consultant Microsoft MVP
Building HTTP Services with ASP.NET Web API Sayed Ibrahim Hashimi Program Manager Microsoft Corporation DEV309.
Testing Web Services Unit Testing, Data Layer Testing, Web API Controllers Testing, Integration Testing Web Services & Cloud SoftUni Team testing Technical.
Model Lync Server 2013 REST API Media Manager (Media State) UI Lync Web App Lync for Windows Phone Lync for iPhone Lync for iPad Lync for.
Private/Public fields, Module, Revealing Module Learning & Development Team Telerik Software Academy.
ASP.NET Web API. ASP.NET Members MS Open Source ASP.NET MVC 4, ASP.NET Web API and ASP.NET Web Pages v2 (Razor) now all open source ASP.NET MVC 4, ASP.NET.
Chapter 3.5 Memory and I/O Systems. 2 Memory Management Memory problems are one of the leading causes of bugs in programs (60-80%) MUCH worse in languages.
Test Driven Development Arrange, Act, Assert… Awesome Jason Offutt Software Engineer Central Christian Church
Data binding concepts, Bindings in WinJS George Georgiev Telerik Software Academy academy.telerik.com Technical Trainer itgeorge.net.
Consuming REST Services from C# SoftUni Team Technical Trainers Software University
Sage ACT! 2013 SDK Update Brian P. Mowka March 23, 2012 Template date: October 2010.
Access to known folders, using pickers, writing to and reading from files, caching files for future access George Georgiev Telerik Software Academy academy.telerik.com.
Plug-In Architecture Pattern. Problem The functionality of a system needs to be extended after the software is shipped The set of possible post-shipment.
 Registry itself is easy and straightforward in implementation  The objects of registry are actually complicated to store and manage  Objects of Registry.
Programming with Java © 2002 The McGraw-Hill Companies, Inc. All rights reserved. 1 McGraw-Hill/Irwin Chapter 5 Creating Classes.
REpresentational State Transfer.  Resources  Representations  Verbs  Links  Headers  HTTP Status Codes.
Getting started with ASP.NET MVC Dhananjay
Copyright 2007 SpringSource. Copying, publishing or distributing without express written permission is prohibited. Spring MVC Essentials Getting started.
Telerik Software Academy Databases.
 An essential supporting structure of any thing  A Software Framework  Has layered structure ▪ What kind of functions and how they interrelate  Has.
Things start to get serious Telerik Software Academy JavaScript OOP.
Learning & Development Mobile apps for iPhone & iPad.
Functions and Function Expressions Closures, Function Scope, Nested Functions Telerik Software Academy
Mocking tools for easier unit testing Telerik Software Academy High Quality Code.
Plug-In Architecture Pattern. Problem The functionality of a system needs to be extended after the software is shipped The set of possible post-shipment.
Entity Framework Database Connection with ASP Notes from started/getting-started-with-ef-using-mvc/creating-an-
WebApi: What is it? How can I use it? Guy In Front of the Whittaker.
Modern Development Technologies in SharePoint SHAREPOINT SATURDAY OMAHA APRIL, 2016.
DNS, DHCP and VPN Borislav Varadinov Telerik Software Academy academy.telerik.com System Administrator
This was written with the assumption that workbooks would be added. Even if these are not introduced until later, the same basic ideas apply Hopefully.
A Presentation Presentation On JSP On JSP & Online Shopping Cart Online Shopping Cart.
Build Robust Web Apps in the Real WakeUpAndCode.com * aka ASP.NET 5 before RC1.
A little more App Inventor and Mind the GAP!
Ukázková aplikace je ke stažení na wug
Introduction to .NET Florin Olariu
ASP.NET Integration Testing
ASP.NET Unit Testing Unit Testing Web API SoftUni Team ASP.NET
JavaScript: Good Practices
Node.js Express Web Applications
MVC Architecture, Symfony Framework for PHP Web Apps
Introduction to Redux Header Eric W. Greene Microsoft Virtual Academy
Tracking and Booking Taxi
Unit Testing & Test-Driven Development for Mere Mortals
Unit testing C# classes
Unit Testing & Test-Driven Development for Mere Mortals
Google App Engine Danail Alexiev
Lecture 1: Multi-tier Architecture Overview
Unit Testing & Test-Driven Development for Mere Mortals
Your code is not just…your code
What’s new in ASP.NET Core and Entity Framework 2.2 (Preview 3)
From Development to Production: Optimizing for Continuous Delivery
From Development to Production: Optimizing for Continuous Delivery
CS4961 Software Design Laboratory Understand Aquila Backend
Plug-In Architecture Pattern
Your code is not just…your code
Presentation transcript:

Unit testing of the Services Telerik Software Academy Web Services and Cloud

 Ways of web service testing  Unit Testing  Integration Testing  Complete Testing of Web Services  Unit testing the data layer  Unit testing the repositories layer  Unit testing the controllers  Integration testing the web services

 Web service unit testing is much like regular unit testing  Writing test methods to test methods etc..  Yet a service is build from many more components than POCO objects  There are the objects, service routing, media types, HTTP Status codes, etc…

 When a web service is ready for test, the testing itself is performed in the following steps:  Write Unit Tests to test the C# objects  Test all objects, their constructors, their methods  Write the Integration Testing  Test the application as if a user tests it

Testing the Work of the Controllers

 The core idea of Unit testing is to test small components of an application  Test a single behavior (a method, property, constructor, etc…)  Unit tests cover all C# components of the app  Models and data layer  Like repositories and DB/XML read/write  Business layer  Controllers and their actions

 The data layer is the one thing that most of the time does not need testing  The idea of the data layer is to reference a data store with a ready-to-use framework  EntityFramework, NHibernate, OpenAccess  They are already tested enough  No point of testing dbContext.Set.Add(), right?

 It is essential to test the implementations of our repositories  The repositories contain the data store logic  All custom (developer) logic must be tested  A missing dbContext.SaveChanges() can cause a lot of pain

 How to test the data store logic?  Writing and deleting the original (production) database is not quite a good option  Imagine a failed test that leaves 100k test records in the database

 A few ways exist to unit test a data store  Manually create a copy of the data store and work on the copy  Backup the original data store, work on the original, and restore the backup when the tests are over  Use transactions, to prevent commit to the data store

 When testing with transactions, the changes done are not really applied to the data store  Whatever commited, if tran.Complete() is not called, the transaction logic is rolled back  How to use transactions in unit tests?  Create a static TransactionScope instance  Initialize the transaction in TestInitialize()  Dispose the transaction in TestCleanup()

Live Demo

 What parts of the repositories should our tests cover?  Test for correct behavior  Add, Delete, Get, All, etc…  Test for incorrect behavior  Test Add with Category that has NULL name

Live Demo

 Testing the services layers actually means testing the controllers and the REST API  Test if controllers work correctly as C# objects  Using mocking or fake repositories  Test if the endpoints of the REST services work correctly  Check the StatusCode and Content

 The Unit testing of the controllers is not much of a big deal  Test them as regular C# classes  Instantiate an object, and test its methods (actions)  The repositories can be mocked/faked for easier testing  If not mocked, the transaction technique should be used again

 To test the controllers, repositories should be faked  i.e. create a in-memory repository that implements the IRepository interface class FakeRepository : IRepository where T:class { IList entities = new List (); IList entities = new List (); public T Add(T entity) { public T Add(T entity) { this.entities.Add(entity); this.entities.Add(entity); return entity; return entity; } public T Get(int id) public T Get(int id) { return this.entities[id]; return this.entities[id]; } …}

 With the Fake Repository present, controllers can be tested by passing their constructor a fake rep public void GetAll_OneCategoryInRepository_ReturnOneCategory() { //arrange var repository = new FakeRepository (); var repository = new FakeRepository (); var categoryToAdd = new Category(){ Name = "Test category" }; var categoryToAdd = new Category(){ Name = "Test category" }; repository.Add(categoryToAdd); repository.Add(categoryToAdd); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoriesModels = controller.GetAll(); var categoriesModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoriesModels.Count() == 1); Assert.IsTrue(categoriesModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoriesModels.First().Name); categoriesModels.First().Name);}

 With the Fake Repository present, controllers can be tested by passing their constructor a fake rep public void GetAll_OneCategoryInRepository_ReturnOneCategory() { //arrange var repository = new FakeRepository (); var repository = new FakeRepository (); var categoryToAdd = new Category(){ Name = "Test category" }; var categoryToAdd = new Category(){ Name = "Test category" }; repository.Add(categoryToAdd); repository.Add(categoryToAdd); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoriesModels = controller.GetAll(); var categoriesModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoriesModels.Count() == 1); Assert.IsTrue(categoriesModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoriesModels.First().Name); categoriesModels.First().Name);} Prepare the repository

 With the Fake Repository present, controllers can be tested by passing their constructor a fake rep public void GetAll_OneCategoryInRepository_ReturnOneCategory() { //arrange var repository = new FakeRepository (); var repository = new FakeRepository (); var categoryToAdd = new Category(){ Name = "Test category" }; var categoryToAdd = new Category(){ Name = "Test category" }; repository.Add(categoryToAdd); repository.Add(categoryToAdd); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoriesModels = controller.GetAll(); var categoriesModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoriesModels.Count() == 1); Assert.IsTrue(categoriesModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoriesModels.First().Name); categoriesModels.First().Name);} Prepare the repository Pass it to the controller

 With the Fake Repository present, controllers can be tested by passing their constructor a fake rep public void GetAll_OneCategoryInRepository_ReturnOneCategory() { //arrange var repository = new FakeRepository (); var repository = new FakeRepository (); var categoryToAdd = new Category(){ Name = "Test category" }; var categoryToAdd = new Category(){ Name = "Test category" }; repository.Add(categoryToAdd); repository.Add(categoryToAdd); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoriesModels = controller.GetAll(); var categoriesModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoriesModels.Count() == 1); Assert.IsTrue(categoriesModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoriesModels.First().Name); categoriesModels.First().Name);} Prepare the repository Pass it to the controller Act on the controller

 With the Fake Repository present, controllers can be tested by passing their constructor a fake rep public void GetAll_OneCategoryInRepository_ReturnOneCategory() { //arrange var repository = new FakeRepository (); var repository = new FakeRepository (); var categoryToAdd = new Category(){ Name = "Test category" }; var categoryToAdd = new Category(){ Name = "Test category" }; repository.Add(categoryToAdd); repository.Add(categoryToAdd); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoriesModels = controller.GetAll(); var categoriesModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoriesModels.Count() == 1); Assert.IsTrue(categoriesModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoriesModels.First().Name); categoriesModels.First().Name);} Prepare the repository Pass it to the controller Act on the controller Assert the result

Live Demo

 Creating fake repository for each and every unit test is kind of boring  Here comes the mocking  Provide objects that mimic some functionality  JustMock/Moq provide mocking functionality  Creates a fake instance of an interface and implement only the functionality needed

[TestMethod] public void GetAll_SingleCategoryInRepository_ReturnsTheCategory() { //arrange //arrange var repository = Mock.Create >(); var repository = Mock.Create >(); var categoryToAdd = GetTestCategory(); var categoryToAdd = GetTestCategory(); IList entities = new List (){ categoryToAdd }; IList entities = new List (){ categoryToAdd }; Mock.Arrange(() => repository.All()) Mock.Arrange(() => repository.All()).Returns(() => entities.AsQueryable()); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoryModels = controller.GetAll(); var categoryModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoryModels.Count() == 1); Assert.IsTrue(categoryModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoryModels.First().Name); categoryModels.First().Name);}

[TestMethod] public void GetAll_SingleCategoryInRepository_ReturnsTheCategory() { //arrange //arrange var repository = Mock.Create >(); var repository = Mock.Create >(); var categoryToAdd = GetTestCategory(); var categoryToAdd = GetTestCategory(); IList entities = new List (){ categoryToAdd }; IList entities = new List (){ categoryToAdd }; Mock.Arrange(() => repository.All()) Mock.Arrange(() => repository.All()).Returns(() => entities.AsQueryable()); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoryModels = controller.GetAll(); var categoryModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoryModels.Count() == 1); Assert.IsTrue(categoryModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoryModels.First().Name); categoryModels.First().Name);} Create the mock object

[TestMethod] public void GetAll_SingleCategoryInRepository_ReturnsTheCategory() { //arrange //arrange var repository = Mock.Create >(); var repository = Mock.Create >(); var categoryToAdd = GetTestCategory(); var categoryToAdd = GetTestCategory(); IList entities = new List (){ categoryToAdd }; IList entities = new List (){ categoryToAdd }; Mock.Arrange(() => repository.All()) Mock.Arrange(() => repository.All()).Returns(() => entities.AsQueryable()); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoryModels = controller.GetAll(); var categoryModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoryModels.Count() == 1); Assert.IsTrue(categoryModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoryModels.First().Name); categoryModels.First().Name);} Create the mock object Mock the All() behavior

[TestMethod] public void GetAll_SingleCategoryInRepository_ReturnsTheCategory() { //arrange //arrange var repository = Mock.Create >(); var repository = Mock.Create >(); var categoryToAdd = GetTestCategory(); var categoryToAdd = GetTestCategory(); IList entities = new List (){ categoryToAdd }; IList entities = new List (){ categoryToAdd }; Mock.Arrange(() => repository.All()) Mock.Arrange(() => repository.All()).Returns(() => entities.AsQueryable()); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoryModels = controller.GetAll(); var categoryModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoryModels.Count() == 1); Assert.IsTrue(categoryModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoryModels.First().Name); categoryModels.First().Name);} Create the mock object Mock the All() behavior Act on the controller

[TestMethod] public void GetAll_SingleCategoryInRepository_ReturnsTheCategory() { //arrange //arrange var repository = Mock.Create >(); var repository = Mock.Create >(); var categoryToAdd = GetTestCategory(); var categoryToAdd = GetTestCategory(); IList entities = new List (){ categoryToAdd }; IList entities = new List (){ categoryToAdd }; Mock.Arrange(() => repository.All()) Mock.Arrange(() => repository.All()).Returns(() => entities.AsQueryable()); var controller = new CategoriesController(repository); var controller = new CategoriesController(repository); //act //act var categoryModels = controller.GetAll(); var categoryModels = controller.GetAll(); //assert //assert Assert.IsTrue(categoryModels.Count() == 1); Assert.IsTrue(categoryModels.Count() == 1); Assert.AreEqual(categoryToAdd.Name, Assert.AreEqual(categoryToAdd.Name, categoryModels.First().Name); categoryModels.First().Name);} Create the mock object Mock the All() behavior Act on the controller Assert the result

Live Demo

 GET actions are easy to test  They return POCO objects  How to test POST actions?  They return HttpResponseMessage  Unfortunately POST actions require additional configuration due to the Request object they use

 A simple POST action: public HttpResponseMessage Post(CategoryModel model) { var entity = this.categoriesRepository.Add(model); var entity = this.categoriesRepository.Add(model); var response = Request.CreateResponse ( var response = Request.CreateResponse ( HttpStatusCode.Created, HttpStatusCode.Created, entity); entity); var resourceLink = Url.Link("DefaultApi", var resourceLink = Url.Link("DefaultApi", new { id = entity.Id }); new { id = entity.Id }); response.Headers.Location = new Uri(resourceLink); response.Headers.Location = new Uri(resourceLink); return response; return response;}

 A simple POST action: public HttpResponseMessage Post(CategoryModel model) { var entity = this.categoriesRepository.Add(model); var entity = this.categoriesRepository.Add(model); var response = Request.CreateResponse ( var response = Request.CreateResponse ( HttpStatusCode.Created, HttpStatusCode.Created, entity); entity); var resourceLink = Url.Link("DefaultApi", var resourceLink = Url.Link("DefaultApi", new { id = entity.Id }); new { id = entity.Id }); response.Headers.Location = new Uri(resourceLink); response.Headers.Location = new Uri(resourceLink); return response; return response;} Run in unit test, Request has a value of null  If a controller is invoked outside of WebAPI environment, the Request object is not set

 To have a non-null value of the Request object, it must be set up manually private void SetupController(ApiController controller) { var request = new HttpRequestMessage() var request = new HttpRequestMessage() { RequestUri = new Uri(" { RequestUri = new Uri(" controller.Request = request; controller.Request = request; var config = new HttpConfiguration(); var config = new HttpConfiguration(); config.Routes.MapHttpRoute( config.Routes.MapHttpRoute( name: "DefaultApi", name: "DefaultApi", routeTemplate: "api/{controller}/{id}", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); defaults: new { id = RouteParameter.Optional }); controller.Configuration = config; controller.Configuration = config; controller.RequestContext.RouteData = new HttpRouteData( controller.RequestContext.RouteData = new HttpRouteData( route: new HttpRoute(), route: new HttpRoute(), values: new HttpRouteValueDictionary { values: new HttpRouteValueDictionary { { "controller", "categories" } { "controller", "categories" } }); });}

 To have a non-null value of the Request object, it must be set up manually private void SetupController(ApiController controller) { var request = new HttpRequestMessage() var request = new HttpRequestMessage() { RequestUri = new Uri(" { RequestUri = new Uri(" controller.Request = request; controller.Request = request; var config = new HttpConfiguration(); var config = new HttpConfiguration(); config.Routes.MapHttpRoute( config.Routes.MapHttpRoute( name: "DefaultApi", name: "DefaultApi", routeTemplate: "api/{controller}/{id}", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); defaults: new { id = RouteParameter.Optional }); controller.Configuration = config; controller.Configuration = config; controller.RequestContext.RouteData = new HttpRouteData( controller.RequestContext.RouteData = new HttpRouteData( route: new HttpRoute(), route: new HttpRoute(), values: new HttpRouteValueDictionary { values: new HttpRouteValueDictionary { { "controller", "categories" } { "controller", "categories" } }); });} Create a Request object

 To have a non-null value of the Request object, it must be set up manually private void SetupController(ApiController controller) { var request = new HttpRequestMessage() var request = new HttpRequestMessage() { RequestUri = new Uri(" { RequestUri = new Uri(" controller.Request = request; controller.Request = request; var config = new HttpConfiguration(); var config = new HttpConfiguration(); config.Routes.MapHttpRoute( config.Routes.MapHttpRoute( name: "DefaultApi", name: "DefaultApi", routeTemplate: "api/{controller}/{id}", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); defaults: new { id = RouteParameter.Optional }); controller.Configuration = config; controller.Configuration = config; controller.RequestContext.RouteData = new HttpRouteData( controller.RequestContext.RouteData = new HttpRouteData( route: new HttpRoute(), route: new HttpRoute(), values: new HttpRouteValueDictionary { values: new HttpRouteValueDictionary { { "controller", "categories" } { "controller", "categories" } }); });} Create a config Create a Request object

Live Demo

 Integration testing aims to cover the work of the whole application  Not small components like unit testing  Integration tests should work like a user  Test what a user sees in combination of all application components mixed together

 When integration testing WebAPI, controllers and their actions are assumed to be working correctly  In WebAPI, integration tests should cover:  The endpoints of the RESTful services  Test if the endpoint reaches the correct action  Test the serialization of the data  Does it work with JSON/XML  Is the data serialized correctly

 Integration testing a GET request: [TestMethod] public void GetAll_SingleCategory_StatusCodeOkAndNotNullContent() { var mockRepository = Mock.Create >(); var mockRepository = Mock.Create >(); var models = new List (); var models = new List (); models.Add(new Category() { Name = "Test Cat" }); models.Add(new Category() { Name = "Test Cat" }); Mock.Arrange(() => mockRepository.All()) Mock.Arrange(() => mockRepository.All()).Returns(() => models.AsQueryable());.Returns(() => models.AsQueryable()); var server = new InMemoryHttpServer ( var server = new InMemoryHttpServer ( " " mockRepository); mockRepository); var response = server.CreateGetRequest("api/categories"); var response = server.CreateGetRequest("api/categories"); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.IsNotNull(response.Content); Assert.IsNotNull(response.Content);}

 Integration testing a GET request: [TestMethod] public void GetAll_SingleCategory_StatusCodeOkAndNotNullContent() { var mockRepository = Mock.Create >(); var mockRepository = Mock.Create >(); var models = new List (); var models = new List (); models.Add(new Category() { Name = "Test Cat" }); models.Add(new Category() { Name = "Test Cat" }); Mock.Arrange(() => mockRepository.All()) Mock.Arrange(() => mockRepository.All()).Returns(() => models.AsQueryable());.Returns(() => models.AsQueryable()); var server = new InMemoryHttpServer ( var server = new InMemoryHttpServer ( " " mockRepository); mockRepository); var response = server.CreateGetRequest("api/categories"); var response = server.CreateGetRequest("api/categories"); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.IsNotNull(response.Content); Assert.IsNotNull(response.Content);} Fake in-memory server, that hosts the WebAPI controllers

Live Demo

форум програмиране, форум уеб дизайн курсове и уроци по програмиране, уеб дизайн – безплатно програмиране за деца – безплатни курсове и уроци безплатен SEO курс - оптимизация за търсачки уроци по уеб дизайн, HTML, CSS, JavaScript, Photoshop уроци по програмиране и уеб дизайн за ученици ASP.NET MVC курс – HTML, SQL, C#,.NET, ASP.NET MVC безплатен курс "Разработка на софтуер в cloud среда" BG Coder - онлайн състезателна система - online judge курсове и уроци по програмиране, книги – безплатно от Наков безплатен курс "Качествен програмен код" алго академия – състезателно програмиране, състезания ASP.NET курс - уеб програмиране, бази данни, C#,.NET, ASP.NET курсове и уроци по програмиране – Телерик академия курс мобилни приложения с iPhone, Android, WP7, PhoneGap free C# book, безплатна книга C#, книга Java, книга C# Николай Костов - блог за програмиране

 Develop a REST API for a BugLogger app  Bugs have status:  fixed, assigned, for-testing, pending  Bugs have text and logDate  Newly added bugs always have status "pending"  Bugs can be queried – get all bugs, get bugs after a date, get only pending bugs, etc… 1. Develop a database in MS SQL Server that keeps the data of the bugs 2. Create repositories to work with the bugs database

3. Provide a REST API to work with the bugs  Using WebAPI  Provide the following actions:  Log new bug  Get all bugs  Get bugs after a specific date:  Get bugs by status  Change bug status 4. Write unit tests to test the BugLogger  Use a mocking framework 5. Write integration tests to test the BugLogger POST …/bugs GET …/bugs GET …/bugs?date= GET …/bugs?type=pending PUT …/bugs/{id}