NancyFX Functional Testing with Autofac - autofac

I've implemented Autofac as my DI Container of choice in place of TinyIoC which is the default in Nancy.
I've got the API working, and I can easily connect to it via the browser, however my functional tests are failing. They're failing because I'm trying to use the Nancy Browser to setup the tests, but it requires the TinyIoC Container (which isn't there).
Is there a simple way to extend/override the Browser to take an Autofac container instead of the TinyIoC one? Alternatively (and probably better), is there a Nancy.Testing Browser that "can" use a different container?
SetUp : System.InvalidOperationException : Something went wrong when
trying to satisfy one of the dependencies during composition, make
sure that you've registered all new dependencies in the container and
inspect the innerexception for more details. ---->
Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type:
Nancy.NancyEngine ----> Nancy.TinyIoc.TinyIoCResolutionException :
Unable to resolve type: Nancy.Routing.DefaultRequestDispatcher ---->
Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type:
Nancy.Routing.DefaultRouteResolver ---->
Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type:
Nancy.Routing.RouteCache ---->
Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type:
TimeTracker.Web.Api.UserModule ---->
Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type:
TimeTracker.Services.IUserService
As you can see, TinyIoC Cannot resolve IUserService.
Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type:
TimeTracker.Services.IUserService
This is because I'm not registering ANYTHING with TinyIoC... Instead I'm registering it with Autofac.
[TestFixtureSetUp]
public void Setup()
{
_browser = new Browser(with =>
{
with.Module<UserModule>();
// forcing me to use TinyIoCContainer
with.ApplicationStartup((x, pipelines) =>
{
var container = BootStrapper.ConfigureContainer(new ContainerBuilder().Build());
var userValidator = container.Resolve<IUserValidator>();
var basicAuthConfig = new BasicAuthenticationConfiguration(userValidator, "TimeTra.ca");
pipelines.EnableBasicAuthentication(basicAuthConfig);
pipelines.OnError.AddItemToEndOfPipeline(
(context, exception) => CustomErrorResponse.FromException(exception));
// Setup a clean database
var migrationRunner = new MigrationRunner(container.Resolve<IDbProvider>());
migrationRunner.DropDatabase();
migrationRunner.CreateDatabase();
BootStrapper.RunMigrations(container);
SeedData.SetupFixtureDataInDatabase(container.Resolve<IServiceLocator>());
});
});
}
private Browser _browser;

If you want to use your Autofac bootstrapper when testing you need to use the Browser(INancyBootstrapper bootstrapper, Action<BrowserContext> defaults = null) constructor and explicitly specify an instance of your bootstrapper.
The problem with this approach is that it will be hard for you to "replace" components for testing purposes, i.e. using mocks etc., that's why the ConfigurableBootstrapper exists. I'm also not quite sure how it will affect module discovery. With the ConfigurableBootstrapper you explicitly say which modules you want to use along with the other services.

Related

Is it possible to enable X-Ray tracing on an EventBridge Eventbus via CDK?

The ability for EventBridge to trace events via X-ray was added earlier this year, see: https://aws.amazon.com/blogs/compute/using-aws-x-ray-tracing-with-amazon-eventbridge/ and https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-related-service-xray.html.
However, this functionality does not yet seem available via the AWS CDK and it seems it might not even be available via the EventBus Cloudformation template. This is the code from CDK that creates the bus
const eventBus = new CfnEventBus(this, 'Resource', {
name: eventBusName,
eventSourceName,
});
which I assume is directly mapping to the CFN template (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-eventbus.html)
{
"Type" : "AWS::Events::EventBus",
"Properties" : {
"EventSourceName" : String,
"Name" : String
}
}
Does anyone know different? If not where would we start to implement this?

Failed to load API definition Fetch Error, when deployed but fine on localhost

I am upgrading my api from netcore2.1 to 3.1
When I run on localhost the UI works fine.
When I deploy via Azure DevOps and go to the myapplication/myapi/swagger.html url I get
Failed to load API definition
Fetch Error
Service Unavailable /myapi/swagger/v1/swagger/json
Yet I can see the json at
myapplication/myapi/swagger/v1/swagger.json
I have the following
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
app.UseSwagger(c =>
c.RouteTemplate = "myapi/swagger/{documentName}/swagger.json"
);
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/myapi/swagger/v1/swagger.json", "Versioned API v1.0");
c.RoutePrefix = "myapi/swagger";
});
return app;
}
I am using
Swashbuckle.AspNetCore (5.2.0)
I found the following worked.
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
app.UseSwagger(c =>
c.RouteTemplate = "myapi/{documentName}/swagger.json"
);
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("./v1/swagger.json", "Versioned API v1.0");
c.RoutePrefix = "myapi";
});
return app;
}
The docs state
If using directories with IIS or a reverse proxy, set the Swagger
endpoint to a relative path using the ./ prefix. For example,
./swagger/v1/swagger.json. Using /swagger/v1/swagger.json instructs
the app to look for the JSON file at the true root of the URL (plus
the route prefix, if used). For example, use
http://localhost://swagger/v1/swagger.json instead
of
http://localhost:///swagger/v1/swagger.json.
However unfortunately my solution doesn't work with Autorest.
Thus I asked another question

Embedded Kafka in micronaut app not finding beans

I'm using the embedded Kafka server in my test described here: https://micronaut-projects.github.io/micronaut-kafka/latest/guide/#kafkaEmbedded. The problem is I'm getting this io.micronaut.context.exceptions.BeanContextException: Error processing bean [Definition: org.app.messaging.TestConsumer] method definition [void receive(String msg)]: Failed to inject value for parameter [testService] of method [setTestService] of class: org.app.messaging.TestConsumer when I run the test. Any ideas how to fix this?
Here's what the test looks like:
void "test run kafka embedded server"() {
given:
ApplicationContext applicationContext = ApplicationContext.run(
Collections.singletonMap(
AbstractKafkaConfiguration.EMBEDDED, true
)
)
when:
AbstractKafkaConsumerConfiguration config = applicationContext.getBean(AbstractKafkaConsumerConfiguration)
Properties props = config.getConfig()
then:
props[ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG] == 9091
when:
KafkaEmbedded kafkaEmbedded = applicationContext.getBean(KafkaEmbedded)
then:
kafkaEmbedded.kafkaServer.isPresent()
kafkaEmbedded.zkPort.isPresent()
cleanup:
applicationContext.close()
}
Placing a test anywhere other than the root package seem to be causing multiple "bean definition not found" issues. There's no ComponentScan support in the framework so the only thing that worked for me was to move the test file to the root package. There's some ideas here: https://github.com/micronaut-projects/micronaut-core/issues/511 if you're experiencing similar issues with a CLI app. However, it didn't work when using the embedded server and embedded kafka.

How can I load a vendor class as a Service in Symfony 4?

I'm using the jwt firebase class in a project, it's path in vendor is:
vendor\firebase\php-jwt\src\jwt
I'm trying to define the class as a service to be able to inject in another class, but I'm not able to do it.
I'm to do this in the service.yml file:
#services.yaml
services:
Firebase:
class: '../vendor\firebase\php-jwt\JWT'
An this is the class I have created:
<?php
namespace App\Helpers;
use Firebase\JWT\JWT;
use Symfony\Component\HttpKernel\KernelInterface;
class simpleJwt
{
private $encrypt = 'RS256';
function __construct(KernelInterface $kernel, JWT $JWT )
{
$this->rootDir = $kernel->getProjectDir();
$this->jwt = $JWT;
}
}
When I try to load it I get this error:
Cannot autowire service "App\Helpers\simpleJwt": argument "$JWT" of method "__construct()" references class "Firebase\JWT\JWT" but no such service exists.
Thanks
Just add full namespace in config.yaml
services:
Firebase\JWT\JWT:
You can also provide to your service constructor requirements, using arguments:
services:
Namespace\Domain\ServiceName:
arguments:
- '#Another\Namespace\Class'
- '#service.name'
- '%parameter%'
More details and features in the official documentation :
Service Container (Symfony Docs)
Note you'll access your service through AutoWiring and that you won't access to it directly through the container, cause service public argument is set to false by default (public: true is not recommended according to Symfony documentation).
Try adding ‘autowire: true’ in your services.yaml, right under ‘class: ../vendor\firebase\php-jwt\JWT’
It could be that the bundle you are trying to import might not be compatible with Symfony’s autowire. Be sure to use the latest version of the bundle (newer versions might be compatible). In case you’re already using the lastest version, you might need to create an alias for that bundle in your services.yaml so you can use it later on your classes. You can use bin/console debug:container to check what services are available and manually create an alias for the service you need. It happens that autowire is commonly turned off in most of the vendor bundles.

Web Api 2 + OWIN 3 + NInject.Web.WebApi.OwinHost, error at startup only

I am building a rest API with Web API2, Owin 3 and NInject Owinhost for my DI.
Using the example provided by NInject, by which I create an "HttpConfiguration" object and call the NInject extension methods in startup.cs, I get an error:
Error activating HttpConfiguration
More than one matching bindings are available.
Matching bindings:
1) binding from HttpConfiguration to method
2) self-binding of HttpConfiguration
3) binding from HttpConfiguration to constant value
Activation path:
1) Request for HttpConfiguration
Suggestions:
1) Ensure that you have defined a binding for HttpConfiguration only once.
My code is as follow in Startup.cs:
public void Configuration(IAppBuilder app)
{
Logger.Info("Entering Startup");
config = new HttpConfiguration();
ConfigureOAuth(app);
// Web API configuration and services
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter("Bearer"));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
var appXmlType =
config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(
t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
app.UseNinjectMiddleware(CreateKernel);
app.UseNinjectWebApi(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
Logger.Info("Exiting Startup");
}
public static StandardKernel CreateKernel()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<HttpConfiguration>().ToSelf().Named("TestHttpConfiguration");
return kernel;
}
The strange thing is when I refresh the page in the browser, the error goes, which leads me to believe that this happens at application startup only.
So I'm confused with this. Has anyone faced the same issue with it?
Thanks
Vincent
I had this same error, as for some reason I had installed both Ninject.Web.WebApi.WebHost and Ninject.Web.WebApi.OwinHost.
If you look in source for OwinWebApiModule.cs and WebApiWebHostModule.cs, both Ninject modules have a binding for HttpConfiguration.
I removed the one I didn't need and things worked.
UPDATE
After trying everything, I managed to get it to work by... Starting a new project from scratch. I had the luxury of doing this because it is a new proof of concept for me.
The main difference here is I installed the packages required (owin 3, ninject) using the Package Manager console rather than the UI. I followed this link here to install those packages.
I then noticed an error message on one of the package as it was looking for Owin 2 dependencies and could not find any. I forced it to install using -DependencyVersion Highest as parameter and it was working fine from the outset.
Unless I missed it I didn't see this error when I installed the packages using the UI. Is it possible the package didn't install properly previously on my other project? Not sure.
Hope this helps someone.