How to component test web api using in memory hosting framework while web api still runs on iis? [closed] - testing

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm trying to create component testing project to test a Web API service and I would like to use in memory hosting solution such as OWIN, I would like to know is it possible and also is it possible that the Web API project would run with IIS and only the testing project will run in memory?
Is there any recommended in memory hosting framework?

You can use Owin to self host your api so you can perform test against a running version of your api. However, you should be able to test your controllers logic using unit tests without requiring your api's to be actually hosted.
Still, there might be valid reason to host them in a unit test so here we go:
Self hosting in a console application is explained here. If it can run in a console application it can run in a unit test project as well. An example could be (pseudo code):
using Microsoft.Owin.Hosting
using Owin
using System.Web.Http
using Microsoft.Owin.Cors
using System.Web.Http.Dispatcher
using System.Threading.Tasks
string service = "http://localhost:54321";
[TestMethod]
public async Task MyTest()
{
using (var webApp = WebApp.Start(service, BuildConfiguration))
{
var requestUrl = string.Format($"{service}/api/Foo/Bar");
var client = new HttpClient();
var response = await client.GetAsync(requestUrl);
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
public void BuildConfiguration(IAppBuilder appBuilder)
{
var HttpConfiguration = new System.Web.Http.HttpConfiguration();
HttpConfiguration.Services.Replace(typeof(IAssembliesResolver), new AssembliesResolver());
HttpConfiguration.MapHttpAttributeRoutes();
HttpConfiguration.Routes.MapHttpRoute("DefaultApi",
$"api/{{controller}}/{{action}}/{{id}}", new { id = RouteParameter.Optional });
appBuilder.UseCors(CorsOptions.AllowAll);
appBuilder.UseWebApi(HttpConfiguration);
HttpConfiguration.EnsureInitialized();
}
[RoutePrefix("api/Foo")]
public class FooController : ApiController
{
[HttpGet]
[Route("Bar")]
public string GetBar()
{
return "Hello World";
}
}
public class AssembliesResolver : DefaultAssembliesResolver
{
private List<Assembly> assemblies;
public override ICollection<Assembly> GetAssemblies()
{
assemblies = new List<Assembly> { GetType().Assembly };
return assemblies;
}
}
Now, your controllers to test probably live in another assembly than in the test assembly. You might have to use an assemblies resolver for the unit test project to be able to discover your api's. You can write your own AssembliesResolver for that as shown in my answer.
Be aware though. Depending on your setup you have to make sure your test environment matches the real world scenario. There might be subtle differences between IIS and self hosted web api's when it comes to the different parameters required to set up the in memory hosting environment

Related

How to start on ServiceStack?

Can you help me point out how should I start on this:
I'm new to API , and I'm currently working on ASP.NET Core 3.1 MVC paired with Microsoft SQL Server. I have requirement that I should use API (ServiceStack) for a certain method.
My question are :
how or where do I start from my existing project solution?
If I use API should it be calling on SQL also? (I supposed the data will stay on db)
with regards to first question : they gave me a link where I can see this.
Where should I start , I'm just so confused.
I've looked up on youtube but there's no similar case to mine, they all use in-memory.
Suggestions and advice are welcome !
Go through ServiceStack's Getting Started Section starting with Create your first Web Service.
Configure OrmLite in your AppHost
To configure OrmLite, start with the OrmLite Installation tells you which package to download whilst the OrmLite Getting Started docs lists all the available SQL Server Dialects which you'd use to configure the OrmLiteConnectionFactory in your IOC.
E.g. for SQL Server 2012:
public class AppHost : AppHostBase
{
public AppHost() : base("MyApp", typeof(MyServices).Assembly) { }
// Configure your ServiceStack AppHost and App dependencies
public override void Configure(Container container)
{
container.AddSingleton<IDbConnectionFactory>(
new OrmLiteConnectionFactory(connectionString,
SqlServer2012Dialect.Provider));
}
}
Using OrmLite in Services
Then inside your ServiceStack Services you can access your ADO .NET DB connection via base.Db which you can use with OrmLite's extension methods, e.g:
public class MyServices : Service
{
public object Any(GetAllItems request) => new GetAllItemsResponse {
Results = Db.Select<Item>()
};
}
Checkout the OrmLite APIs docs for different APIs to Select, Insert, Update & Delete Data.
Creating effortless RDBMS APIs using AutoQuery
As you're new I'd highly recommend using AutoQuery RDBMS since it lets you create RDBMS APIs with just Request DTOs.
You can enable it by adding the AutoQueryFeature plugin in the ServiceStack.Server" NuGet package:
public override void Configure(Container container)
{
Plugins.Add(new AutoQueryFeature { MaxLimit = 100 });
}
Then you can create an AutoQuery API for your Item table with just:
[Route("/items")]
public class QueryItems : QueryDb<Item> {}
Which will now let you query each Item column using any of AutoQuery's implicit conventions, e.g by exact match:
/items?Id=1
Or by any of the query properties:
/items?NameStartsWith=foo
Creating Typed Request DTO
Once you know which Query APIs your client Apps needs I'd recommend formalizing them by adding them as strong typed properties in your Request DTO, e.g:
[Route("/items")]
public class QueryItems : QueryDb<Item>
{
public int? Id { get; set; }
public string NameStartsWith { get; set; }
}
Calling from Service Clients
Which will enable an end-to-end Typed API using any of ServiceStack's Service Clients, e.g:
var client = new JsonServiceClient(BaseUrl);
var response = client.Get(new QueryItems { NameStartsWith = "foo" });
response.PrintDump(); // quickly view results in Console
There's also AutoQuery CRUD APIs that will let you create APIs that modify your RDBMS tables using just Request DTOs.

Integrate swashbuckle swagger with odata in ASP.Net Core [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have tried to implement both ( swagger and odata ) in asp.net core, but it's not working.
I'm unable to integrate the route given for odata.
I have the following Configuration and I receive a generic error.
This is the error
We ran into the same issue when adding OData to our .Net Core project. The workarounds shown in the code snippet on this post fixed our API error(s) when Swagger UI loads.
As far as I can tell, OData isn't supported in Swashbuckle for AspNetCore. So after adding the workaround code in the link above, our Swagger UI works, but none of the OData endpoints show.
Code snippet from the link:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddOData();
// Workaround: https://github.com/OData/WebApi/issues/1177
services.AddMvcCore(options =>
{
foreach (var outputFormatter in options.OutputFormatters.OfType<ODataOutputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
{
outputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
}
foreach (var inputFormatter in options.InputFormatters.OfType<ODataInputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
{
inputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
}
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var builder = new ODataConventionModelBuilder(app.ApplicationServices);
builder.EntitySet<Product>("Products");
app.UseMvc(routebuilder =>
{
routebuilder.MapODataServiceRoute("ODataRoute", "odata", builder.GetEdmModel());
// Workaround: https://github.com/OData/WebApi/issues/1175
routes.EnableDependencyInjection();
});
}
}
I was able to do this using a DocumentFilter. Create a class like the example below, then add it to your Swagger configuration as:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info { Title = "Your title API v1.0", Version = "v1.0" });
options.DocumentFilter<CustomDocumentFilter>();
});
Github Example
You can integrate Swagger a couple of different ways. For barebones support, you can use the ODataSwaggerConverter provided by OData. This will effectively convert the EDM to a Swagger document. To wire this up to a Swagger generator library like Swashbuckle, you just need create and register a custom generator. The UI and client side of things should remain unchanged. If the generated Swagger document isn't sufficient, the base implementation of the ODataSwaggerConverter is still a reasonable start.
If you're using API Versioning for OData with ASP.NET Core, you need only add the corresponding API Explorer package. Swashuckle will light up with little-to-no additional work on your part. The ASP.NET Core with OData Swagger sample application has an end-to-end working example.

How to run XUnit test on both self-host & production webapi service?

I'd like to write a test for my ASP.NET WebApi service and run it against a self-hosted service and the live web hosted service. I imagine that this can be done with a test fixture, but I'm not sure how to set it up. Does anyone know of an example of using a configurable test fixture so that you can pass a parameter to Xunit to choose a self hosted fixture or a web hosted fixture?
Here is how it works with latest xUnit 2.0 beta.
Create a fixture:
public class SelfHostFixture : IDisposable {
public static string HostBaseAddress { get; private set; }
HttpSelfHostServer server;
HttpSelfHostConfiguration config;
static SelfHostFixture() {
HostBaseAddress = ConfigurationManager.AppSettings["HostBaseAddress"]; // HttpClient in your tests will need to use same base address
if (!HostBaseAddress.EndsWith("/"))
HostBaseAddress += "/";
}
public SelfHostFixture() {
if (/*your condition to check if running against live*/) {
config = new HttpSelfHostConfiguration(HostBaseAddress);
WebApiConfig.Register(config); // init your web api application
var server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
}
}
public void Dispose() {
if (server != null) {
server.CloseAsync().Wait();
server.Dispose();
server = null;
config.Dispose();
config = null;
}
}
}
Then define a collection that will use that fixture. Collections are the new concept to group tests in xUnit 2.
[CollectionDefinition("SelfHostCollection")]
public class SelfHostCollection : ICollectionFixture<SelfHostFixture> {}
It serves as just a marker so has no implementation.
Now, mark tests that rely on your host to be in that collection:
[Collection("SelfHostCollection")]
public class MyController1Test {}
[Collection("SelfHostCollection")]
public class MyController4Test {}
The runner will create a single instance of your fixture when running any test from within MyController1Test and MyController4Test ensuring that your server is initiated only once per collection.
I would recommend to use the In-Memory Server for testing your controllers, so you don't need to spin up a self-host in your unit tests.
http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx

Recommended patterns for unit testing web services

We are about to begin architecting a service oriented framework (SOA) which will certainly involve a high number of of granular web services (REST in WCF). We've been quite disciplined in unit testing our client and server-side code base, however we don't have much of any experience in unit testing web services. We're really looking for guidance as to where the tests should be written and recommendations on what approach to use when unit testing our services.
Should we write tests that make http requests and assert that the responses are what they should be? Should we focus on just testing the internal logic of the service methods themselves and not worry about testing the actual requests? Or should we do both? Are there any other recommendations for what we should be testing?
We're really looking for some explanation and guidance and would truly appreciate any advice we can get.
I have found testing web services, specifically WCF client and server, useful on top of regular unit testing in the following scenarios:
Acceptance testing where you want to black box test your whole service and poke things in at the extremities.
Testing a specific WCF wire up, extension, behavior, etc.
Testing that your interface and your data members are setup correctly.
Most of the time I try to use a very basic setup with basic http and wire everything up in the code. Unless I am Integration or Acceptance testing I don't test the client against the server, instead I mock one of them so that I can test the other in isolation. Below are examples of how I test WCF clients and services:
public static ServiceHost CreateServiceHost<TServiceToHost>(TServiceToHost serviceToHost, Uri baseAddress, string endpointAddress)
{
var serviceHost = new ServiceHost(serviceToHost, new[] { baseAddress });
serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
serviceHost.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
serviceHost.AddServiceEndpoint(typeof(TServiceToHost), new BasicHttpBinding(), endpointAddress);
return serviceHost;
}
//Testing Service
[TestFixture]
class TestService
{
private ServiceHost myServiceUnderTestHost;
private ChannelFactory<IMyServiceUnderTest> myServiceUnderTestProxyFactory;
[SetUp]
public void SetUp()
{
IMyServiceUnderTest myServiceUnderTest = new MyServiceUnderTest();
myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint");
myServiceUnderTestHost.Open();
myServiceUnderTestProxyFactory = new ChannelFactory<IMyServiceUnderTest>(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345/ServiceEndPoint"));
}
[TearDown]
public void TearDown()
{
myServiceUnderTestProxyFactory.Close();
myServiceUnderTestHost.Close();
}
[Test]
public void SomeTest()
{
IMyServiceUnderTest serviceProxy = myServiceUnderTestProxyFactory.CreateChannel();
serviceProxy.SomeMethodCall();
}
}
//Testing Client
[TestFixture]
class TestService
{
private ServiceHost myMockedServiceUnderTestHost;
private IMyServiceUnderTest myMockedServiceUnderTest;
[SetUp]
public void SetUp()
{
myMockedServiceUnderTest = Substitute.For<IMyServiceUnderTest>(); //Using nsubstitute
myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myMockedServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint");
myServiceUnderTestHost.Open();
}
[TearDown]
public void TearDown()
{
myServiceUnderTestHost.Close();
}
[Test]
public void SomeTest()
{
//Create client and invoke methods that will call service
//Will need some way of configuring the binding
var client = new myClientUnderTest();
client.DoWork();
//Assert that method was called on the server
myMockedServiceUnderTest.Recieved().SomeMethodCall();
}
}
NOTE
I had forgot to mention that if you want to mock a WCF service using anything that uses castles dynamic proxy then you will need to prevent the ServiceContractAttribute from being copied to the mock. I have a blog post on this but basically you register the attribute as one to prevent from replication before you create the mock.
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating
.Add<ServiceContractAttribute>();
Well basically I think that you need to have a two part test strategy.
The first part would be true unit tests, which would involve testing the classes completely independent of any web request ... as the main definition of a unit test is one that runs without the need of extra environments or setups other than the ones in the test itself.
So you would create unit test projects, in which you would instantiate the code classes of your WCF services to make sure the logic is correct, in much the same way that you test the rest of your classes.
The second part would be a set of integration tests, which would test your application in an end-to-end fashion. Of course, here you need the whole enchilada, web server, database, and so forth.
This way you know that your logic is accurate and also that your application works.

Testing Castle windsor Component with PerWebRequest lifestyle

I'm trying to do some testing with castle windsor involved, in one of my tests I want to check the windsor installers, so I check that the container can resolve my components given its interface.
So far, so good, the problem starts when the component has PerWebRequest lifestyle in its installer, at first it complained about HttpContext.Current is null, having that one solved creating a fake Context in test setup I'm now having this exception in nunit test
System.Exception : Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
Add '' to the section on your web.config. If you're running IIS7 in Integrated Mode you will need to add it to section under
As I'm running this from NUnit, how I can register the module or class in windsor so it works, or how can be mocked, as in this test is not really a web request, just checking that the container resolve the type.
And also this same thing will happen if I make any integration tests with this component outside a real webrequest, is there any way to make this work or really mock a web request so this tests can be run?
Tranks in advance
Fer
In your test you could subscribe to the ComponentModelCreated event and change the lifestyle of your per-web-request components to something else. (example).
If you're writing an integration test with the scope of a single request, singleton should do.
If you're writing an integration test that spans multiple requests, you could use a contextual lifestyle to simulate the scope of requests.
Edit: including code from example (which is no longer available):
container.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
…
void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
if (model.LifestyleType == LifestyleType.Undefined)
model.LifestyleType = LifestyleType.Transient;
}
From version 5 of Windsor the accepted answer doesn't work if you are using Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor because the PerWebRequest lifestyle is already a scoped lifestyle.
I got it to work by changing the the ComponentModelCreated delegate to the following:
void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
const string CastleScopeAccessorType = "castle.scope-accessor-type";
if (model.ExtendedProperties.Contains(CastleScopeAccessorType))
{
model.ExtendedProperties.Remove(CastleScopeAccessorType);
}
}
I ended up implementing this extension. ATTN: Must call before loading components with the PerWebRequest lifestyle:
public static class WindsorContainerExtensions
{
public static IWindsorContainer OverridePerWebRequestLifestyle(this IWindsorContainer container)
{
container.Kernel.ComponentModelCreated += model =>
{
if (model.IsPerWebRequestLifestyle())
{
model.LifestyleType = LifestyleType.Transient;
}
};
return container;
}
private static bool IsPerWebRequestLifestyle(this ComponentModel model)
{
return model.LifestyleType == LifestyleType.Scoped
&& model.HasAccessorType(typeof(WebRequestScopeAccessor));
}
private static bool HasAccessorType(this ComponentModel model, Type type)
=> model.HasExtendedProperty("castle.scope-accessor-type", type);
private static bool HasExtendedProperty<T>(this ComponentModel model, object key, T expected)
{
return model.ExtendedProperties[key] is T actual
&& EqualityComparer<T>.Default.Equals(actual, expected);
}
}
Requires these imports:
using System;
using System.Collections.Generic;
using Castle.Core;
using Castle.Facilities.AspNet.SystemWeb;
using Castle.Windsor;
If you also want to check if the type of scope is per web request you could also do this
var isPerWebRequestScope = JsonConvert.SerializeObject(model.ExtendedProperties).Contains("Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor")