Use web project config.json when doing integration testing - testing

I am using ASP.NET 5 RC1 and I need to write integration tests ...
So on the Test project, ASPNET5_WEB_TEST, I have the following:
public class IntegrationTests {
private readonly TestServer _server;
private readonly HttpClient _client;
public IntegrationTests() {
_server = new TestServer(TestServer.CreateBuilder().UseStartup<Startup>());
_client = _server.CreateClient();
}
// Test methods ...
}
The Startup class is from the ASP.NET 5 project I am testing: ASPNET5_WEB
When I run the test I get the following error:
The configuration file 'C:\Projects\ASPNET5_TEST\config.json' was not found and is not optional.
I know I get this error because on Startup I have:
builder
.AddJsonFile("config.json", false)
.AddJsonFile($"config.{environment.EnvironmentName}.json", true);
To fix this error I need to copy, at least, config.json from my web project, ASPNET5_WEB, to my test project, ASPNET5_WEB_TEST. But this means I will need to maintain duplicate config.json or at least copy it every time I make a change.
Can't I tell TestServer to use Startup of the web project and also its config.*.json files?
And can I have a config.testing.json and set on the TestServer the environment to Testing so the Startup code uses config.json and config.testing.json?

I assume you're using the TestServer from aspnet, if so, it wasn't built to support the way you're config files are read. The TestServer is used to run simple integration tests for their "hosting engine" but not for integrations tests for a website.
Their ApplicationDeployerFactory class is what you can use however. Refer to this as an example of how to run an "integration" server. I've used selenium in conjunction with that to run integration tests against the project I'm working on atm.

Yes, you can.
Take a look at this issue https://github.com/aspnet/Mvc/issues/3410 and The mentioned package.
Basically you need to implement your own IApplicationEnvironment

Related

How to provide an HttpClient to ktor server from the outside to facilitate mocking external services?

I am trying to provide an HttpClient from the outside to my ktor server so that I can mock external services and write tests, however I get this exception when I run my test:
Please make sure that you use unique name for the plugin and don't install it twice. Conflicting application plugin is already installed with the same key as `Compression`
io.ktor.server.application.DuplicatePluginException: Please make sure that you use unique name for the plugin and don't install it twice. Conflicting application plugin is already installed with the same key as `Compression`
at app//io.ktor.server.application.ApplicationPluginKt.install(ApplicationPlugin.kt:112)
at app//com.example.plugins.HTTPKt.configureHTTP(HTTP.kt:13)
at app//com.example.ApplicationKt.module(Application.kt:14)
at app//com.example.ApplicationTest$expected to work$1$1.invoke(ApplicationTest.kt:39)
at app//com.example.ApplicationTest$expected to work$1$1.invoke(ApplicationTest.kt:38)
and thats a bit unexpected to me because I am not applying the Compression plugin twice as far as I can tell. If I run the server normally and manually call my endpoint with curl then it works as expected. What am I doing wrong?
I added a runnable sample project here with a failing test.
sample project
official ktor-documentation-sample project.
The problem is that you have the application.conf file and by default, the testApplication function tries to load modules which are enumerated there. Since you also explicitly load them in the application {} block the DuplicatePluginException occurs. To solve your problem you can explicitly load an empty configuration instead of the default one:
// ...
application {
module(client)
}
environment {
config = MapApplicationConfig()
}
// ...

Set Environment=Development when xunit testing an ASP.NET Core app

I xUnit test my ASP.NET Core web app, and my test class includes:
this.host = Program.CreateHostBuilder(Array.Empty<string>()).Build();
in order to access host.Services.
I discover that the host has Environment=Production. So the configuration seen in my startup file ignores appsettings.Development.json.
How do I inject or force host to have Environment=Development?
Preferably without any code in the web app itself.
(Context: I'm using JetBrains Rider. I find nothing in Rider setup or configuration that lets me choose an Environment for a UnitTest session. But if there is a solution on that line the question still stands)
I had assumed—wrongly—that I might fix it with this:
this.host = Program.CreateHostBuilder(
"ASPNETCORE_ENVIRONMENT=Development"
).Build();
because the docs say
The default configuration loads environment variables and command line arguments prefixed with DOTNET_ and ASPNETCORE_
but what fixed it was:
this.host = Program.CreateHostBuilder(
"ENVIRONMENT=Development"
).Build();
With this, the Configuration element then picked up the appsettings.Development.json file instead of ignoring it.
( So now I wonder whether part of the env variable processing is done by the dotnet executable before reaching Program.Main() )

EF6 localdb for integration testing

I am developing a WPF application which requires some database access. For development purposes I am using localdb with database migrations enabled and EF6.
What I cannot figure out is how do I configure a separate localdb database for integration tests inside a VS2013 test project and run the database migrations to bring it up to date and then seed it with data.
Here's what I've ended up doing based off information from several sources. First, in the App.Config of my test project I've added the following
<connectionStrings>
<add name="YourContextName" connectionString="Data Source=(localdb)\mssqllocaldb;Integrated Security=true;AttachDBFilename=|DataDirectory|\databasename.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
Then I created the following class:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data.Entity;
using MyProject.Model.Entities;
using MyProject.Migrations;
namespace IntegrationTests
{
public class DatabaseInitializer : DropCreateDatabaseAlways<MyProjectDataContext>
{
}
[TestClass]
public class Initalize
{
[AssemblyInitialize]
public static void AssemblyInit(TestContext context)
{
AppDomain.CurrentDomain.SetData("DataDirectory", context.TestDeploymentDir);
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyProjectDataContext, Configuration>());
//Database.SetInitializer(new DatabaseInitializer());
}
}
}
My understanding is that this runs before each test run. The SetData call updates the |DataDirectory| used in the App.Config so that it is unique and doesn't try to use the same instance as the normal project.
From there I have the choice of either running the migrations and then supplying some test data as part of the test or to run an initializer that sets up the test data. Note that to run the migrations the configuration class generated by the migration must be changed from internal to public.
This seems to work so far. Not sure if this is the best way or if I can combine the migrations and then run a different seed for the tests.
Within your test project, you could set Database.SetInitializer() (or databaseInitializer within the project config file) with MigrateDatabaseToLatestVersion or with your own IDatabaseInitializer that calls DbMigrator.Update, and use a custom DbMigrationsConfiguration.
The test project could use a separate connection string for using LocalDB, and if the file referenced by your connection string's AttachDBFilename, then the initializer will try to create it.
Might be helpful: Recreate and Reseed LocalDb Before Each Unit Test
...But DropCreateDatabaseAlways won't work with EF6 migrations

Hot re-deployment of a RESTlet

I'm interested in setting up a super lightweight web server with Restlet mostly for proofs-of-concept and low impedance collaboration with other developers. A full servlet container feels too heavy. Literally, I'm starting with something pulled directly from the "Getting Started" guide.
public class Dummy extends ServerResource {
public static void main(String[] args) throws Exception {
new Server(Protocol.HTTP, 8182, Dummy.class).start();
}
#Get("json")
public String hello() {
ST hello = new ST();
hello.add("name", "World");
return "{ \"hello\": \"World\"}";
}
}
However, I'd like to be able to watch for changes and redeploy automatically as I change code. I know Jetty can do this with some config. Has anyone done this without setting up a full servlet container? Is there something simpler?
I use Eclipse as my IDE to edit the code and launch the app, but the ideal solution wouldn't rely on that.
This what I call Continuous Delivery.
In a nutshell:
I usually use
SVN or Git to store and version source code
Jenkins to schedule the build and deployment
Gradle or Maven to build and test
The SCM plugin is able to poll the repository and invoke the process only if there is changes, or you can trigger the build with a hook.
There are plugins to copy your artifact to the target server and restart the application.

No coverage results using the eclEmma plugin for server code in a gwt application

I'm using the eclEmma plugin to test code coverage for my gwt application. I've written jUnit test classes for client code, such as testing get/set methods etc. as well as jUnit tests for rpc services. I used "syncproxy" to test my equivalent GreetService, GreetServiceAsync and GreetServiceImpl rpc services. For example I have a location service that gets a users location and this is part of my test class:
public class LocationServiceTest {
private static LocationService rpcService =
(LocationService) SyncProxy.newProxyInstance(LocationService.class,
"http://localhost:...", "location");
#Test
public void testAdministrativeAreaLevel2LocationService() {
String result = rpcService.getAddress("49.28839970000001,-123.1259316");
assertTrue((result != null) && (result.startsWith("Vancouver")));
}
The jUnit tests all pass, but when I run eclEmma on my project (I right click the project, select "Coverage as" then "jUnit test") I only get coverage results for client code, and 0% coverage for all my server code.
Any suggestions for how to get eclEmma to cover server code? Or for what I might be doing wrong?
EclEmma tracks coverage on code launched at the test jvm (the vm you launch when you run the test). You seem to be running your server before, so eclEmma "can't see" its coverage. You could try running the server inside your tests, with Cargo, for example.