Testing asp.net 5 vnext middleware from a TestServer - unit-testing

In owin, its possible to test a web api in unit test using a TestServer (see this blog).
Is this functionality available for asp.net 5 middleware ?
UPDATE:
based on responses below, I tried to use TestServer, but visual studio complains that 'The type or namespace name 'AspNet' does not exist in the namespace 'Microsoft' (are you .....'
I use Visual Studio 2015
in my nuget sources (settings) I have (https://www.myget.org/F/aspnetmaster/)
(I also tried with https://www.myget.org/F/aspnetvnext/, but got the same problem)
here is my project.json file
{
"version": "1.0.0-*",
"dependencies": {
"Microsoft.AspNet.Http": "1.0.0-*",
"Microsoft.AspNet.TestHost": "1.0.0-*",
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Testing" : "1.0.0-*",
"xunit": "2.1.0-beta1-*",
"xunit.runner.aspnet": "2.1.0-beta1-*",
"Moq": "4.2.1312.1622",
"Shouldly": "2.4.0"
},
"commands": {
"test": "xunit.runner.aspnet"
},
"frameworks" : {
"aspnet50" : {
"dependencies": {
}
}
}
}

It is available on ASP.NET 5 as well: Microsoft.AspNet.TestHost.
Here is a sample. Middleware:
public class DummyMiddleware
{
private readonly RequestDelegate _next;
public DummyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("DummyMiddleware");
context.Response.ContentType = "text/html";
context.Response.StatusCode = 200;
await context.Response.WriteAsync("hello world");
}
}
Test:
[Fact]
public async Task Should_give_200_Response()
{
var server = TestServer.Create((app) =>
{
app.UseMiddleware<DummyMiddleware>();
});
using(server)
{
var response = await server.CreateClient().GetAsync("/");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
}
You can find more about the usage of the TestServer class on the tests.

Related

Postman Windows Authentication (NTLM) not working

I have created a brand new WebAPI project from Visual Studio template. Target Framework netcoreapp3.1. I have configured it with windows authentication. I created a request in Postman with NTLM configuration to call my API. When I debug my application and call the request via Postman I get the following error:
IIS 10.0 Detailed Error - 401.1 - Unauthorized
My Startup class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace WebApplication1
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
My Controller class:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries =
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
}
launchSettings.json:
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:52109",
"sslPort": 44396
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WebApplication1": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Postman config with result:
Postman auth config:
I have no clue what's the problem :-( I have called my API from Insomnia or SoapUI and it works just fine! Maybe my problem is related to that issue https://github.com/postmanlabs/postman-app-support/issues/8038

Integrated Unit Testing is not running in ASP.NET core MVC/Web API

I am developing a web API using ASP.Net core. I am doing integrated testing to my project. I am following this link, https://koukia.ca/integration-testing-in-asp-net-core-2-0-51d14ede3968. This is my code.
I have the controller to be tested in the thegoodyard.api project.
namespace thegoodyard.api.Controllers
{
[Produces("application/json")]
[Route("api/category")]
public class CategoryController: Controller
{
[HttpGet("details/{id}")]
public string GetCategory(int id = 0)
{
return "This is the message: " + id.ToString();
}
}
}
I added a new unit test project called thegoodyard.tests to the solution. I added a TestServerFixture class with the following definition
namespace thegoodyard.tests
{
public class TestServerFixture : IDisposable
{
private readonly TestServer _testServer;
public HttpClient Client { get; }
public TestServerFixture()
{
var builder = new WebHostBuilder()
.UseContentRoot(GetContentRootPath())
.UseEnvironment("Development")
.UseStartup<Startup>(); // Uses Start up class from your API Host project to configure the test server
_testServer = new TestServer(builder);
Client = _testServer.CreateClient();
}
private string GetContentRootPath()
{
var testProjectPath = PlatformServices.Default.Application.ApplicationBasePath;
var relativePathToHostProject = #"..\..\..\..\..\..\thegoodyard.api";
return Path.Combine(testProjectPath, relativePathToHostProject);
}
public void Dispose()
{
Client.Dispose();
_testServer.Dispose();
}
}
}
Then again in the test project, I created a new class called, CategoryControllerTests with the following definition.
namespace thegoodyard.tests
{
public class CategoryControllerTests: IClassFixture<TestServerFixture>
{
private readonly TestServerFixture _fixture;
public CategoryControllerTests(TestServerFixture fixture)
{
_fixture = fixture;
}
[Fact]
public async Task GetCategoryDetai()
{
var response = await _fixture.Client.GetAsync("api/category/details/3");
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
bool containMessage = false; //responseString.Contains("This is the message: 3"); - I commented on purpose to make the test fails.
Assert.True(containMessage);
}
}
}
Then I right on the test method and clicked run tests in the option to run the test. But none of the tests was run. This is the output.
What is missing in my code? How can I get my integrated test running?
Please check following NuGet packages in your project:
Microsoft.AspNetCore.TestHost
Microsoft.NET.Test.Sdk
xunit
xunit.runner.visualstudio
Perhaps there's a build error that's preventing the project from being compiled. There's really not enough information here to say for sure. Rebuild your solution, and ensure there's no errors.
Aside from that, you can remove some variables by reducing the test code needed. ASP.NET Core includes a WebApplicationFactory<TEntryPoint> fixture out of the box for bootstrapping a test server. You can therefore change your test code to just:
public class CategoryControllerTests: IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public CategoryControllerTests(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
[Fact]
public async Task GetCategoryDetail()
{
var client = _factory.CreateClient();
var response = await client.GetAsync("api/category/details/3");
...
See the documentation for additional information and more advanced scenarios.
This way works fine for xUnit based intergration tests, which use Startup configuration. the code blow also demonstrates how to override some settings in appSetting.json to specific values for testing, as well as how to access to DI services.
using System;
using System.Net.Http;
using MyNamespace.Web;
using MyNamespace.Services;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace MyNamespace.Tests
{
public class TestServerDependent : IDisposable
{
private readonly TestServerFixture _fixture;
public TestServer TestServer => _fixture.Server;
public HttpClient Client => _fixture.Client;
public TestServerDependent()
{
_fixture = new TestServerFixture();
var myService = GetService<IMyService>();
// myService.PerformAnyPreparationsForTests();
}
protected TService GetService<TService>()
where TService : class
{
return _fixture.GetService<TService>();
}
public void Dispose()
{
_fixture?.Dispose();
}
}
public class TestServerFixture : IDisposable
{
public TestServer Server { get; }
public HttpClient Client { get; }
public TestServerFixture()
{
var hostBuilder = WebHost.CreateDefaultBuilder()
.ConfigureAppConfiguration(
(builderContext, config) =>
{
var env = builderContext.HostingEnvironment;
config
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile("appsettings.Testing.json", optional: false,
reloadOnChange: true);
})
.ConfigureLogging(
(hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseStartup<Startup>();
Server = new TestServer(hostBuilder);
Client = Server.CreateClient();
}
public void Dispose()
{
Server.Dispose();
Client.Dispose();
}
public TService GetService<TService>()
where TService : class
{
return Server?.Host?.Services?.GetService(typeof(TService)) as TService;
}
}
}
How the simple integration test might look like with the described above:
using System.Net;
using Xunit;
namespace MyNamespace.Tests
{
public class SimpleIntegrationTest : TestServerDependent
{
[Fact]
public void RedirectToLoginPage()
{
var httpResponseMessage = Client.GetAsync("/").Result;
// Smoke test to make sure you are redirected (to Login page for instance)
Assert.Equal(HttpStatusCode.Redirect, httpResponseMessage.StatusCode);
}
}
}

how to do cypress unit tests with vue/cli

I am using vue/cli 3 configured for cypress e2e tests. The e2e test scenario works fine but I also wish to use cypress for unit tests. I installed cypress-vue-unit-test but when loading a single component (using mountVue) cypress fails to interpret the Vue syntax ( etc).
I presume I have to add configuration so that the correct web pack loaders are used at the preprocessor stage when cypress bundles the files. I have been unable to figure out how to accomplish this as there is no web pack config file in my project and I am not sure how to modify the preconfigured set-up. Can anyone guide me?
Thanks phoet, you pointed me in the right direction. The solution was to place the configuration in tests/e2e/plugins/index.js with the following content (probably could be refined):
const webpack = require("#cypress/webpack-preprocessor");
const VueLoader = require("vue-loader/lib/plugin");
const webpack_vue_cypress_config = {
webpackOptions: {
module: {
rules: [
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.css$/,
use: ["vue-style-loader", "css-loader"]
}
]
},
resolve: {
extensions: [".js", ".vue", ".json"],
alias: {
vue$: "vue/dist/vue.esm.js",
"#": "../../"
}
},
plugins: [new VueLoader()]
},
watchOptions: {}
};
module.exports = (on, config) => {
on("file:preprocessor", webpack(webpack_vue_cypress_config));
return Object.assign({}, config, {
fixturesFolder: "tests/e2e/fixtures",
integrationFolder: "tests/e2e/specs",
screenshotsFolder: "tests/e2e/screenshots",
videosFolder: "tests/e2e/videos",
supportFile: "tests/e2e/support/index.js"
});
};
Thanks Linus; that's much cleaner
const webpack = require("#cypress/webpack-preprocessor");
const options = {
webpackOptions: require("#vue/cli-service/webpack.config.js"),
watchOptions: {}
};
module.exports = (on, config) => {
on("file:preprocessor", webpack(options));
return Object.assign({}, config, {
fixturesFolder: "tests/e2e/fixtures",
integrationFolder: "tests/e2e/specs",
screenshotsFolder: "tests/e2e/screenshots",
videosFolder: "tests/e2e/videos",
supportFile: "tests/e2e/support/index.js"
});
};

Application error : The connection to the server was unsuccessful. (file:///android_asset/www/index.html)

On calling my web service from my app.component.ts file I am getting the below error when I run the app in VS Emulator for Android. Can someone please provide a solution?
In the ngOnInit() life cycle hook of app.component.ts I am accessing the data from the web service class
app.component.ts(excerpt)
ngOnInit()
{
this.myDataService.openWebMwthod()
.subscribe((response)=>{
this.datas = response;
JSON.stringify(this.datas);
alert("here"+this.datas);
if(this.datas == null || this.datas == "")
{
this.nav.setRoot(this.accessDeniedPage, {showFooter : false});
}
else
{
this.nav.setRoot(this.homePage, {showFooter : false});
}
});
}
Below is my Web Service class excerpt where I am making a REST call:
my-mobile.dataservice(excerpt)
public openWebMwthod() : Observable<any>{
this.initializeApp();
let details = {
"EmpID" : this.sapId
};
let body = JSON.stringify(details);
let headers = new Headers(
{
'Content-Type': 'application/json',
}
);
let options = new RequestOptions({headers:headers});
return this.http.post(URL,body,options)
.map( (res) => res.json())
}
Just add this code to your config.xml
<preference name="loadUrlTimeoutValue" value="700000" />

NUnit test not working with Entity Framework ToListAsync()

The source IQueryable doesn't implement IDbAsyncEnumerable.
Only sources that implement IDbAsyncEnumerable can be used for Entity Framework asynchronous operations.
For more details see http://go.microsoft.com/fwlink/?LinkId=287068.
I am new to NUnit.
I have developed the Nunit test cases for` async queries.
But I am getting above error. I refereed https://msdn.microsoft.com/en-us/data/dn314429.aspx link but not able
to solve error.
Any kind of help will be appreciated!
Thanks in advance!
public interface IWork : IDisposable
{
IBlogRepository BlogRepository { get; }
IDBContext Db { get; }
}
public class BlogRepository : GenericRepository<Blog>, IBlogRepository
{
internal ContainerRepository(IWork work)
: base(work)
{
}
}
public interface IBlogRepository : IGenericRepository<Blog>
{
}
[TestFixture]
public class AsyncQueryTests
{
[Test]
public async Task GetAllBlogsAsync_orders_by_name()
{
using (var work = ObjectFactory.GetInstance<IWork>())
{
var data = new List<Blog>
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
}.AsQueryable();
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IDbAsyncEnumerable<Blog>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<Blog>(data.GetEnumerator()));
mockSet.As<IQueryable<Blog>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<Blog>(data.Provider));
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<IWork>();
mockContext.Setup(c => c.BlogRepository.GetQuery()).Returns(mockSet.Object);
ObjectFactory.Configure(cfg => cfg.For<IWork>().Use(mockContext.Object));
foreach (var blog in mockSet.Object)
{
mockContext.Object.BlogRepository.Add(blog);
}
var service = new BlogController();
var blogs = await service.GetAllBlogsAsync();
Assert.AreEqual(3, blogs.Count);
}
}
}