host.json not respected by Visual Studio or web job - azure-webjobs

I have a queue processing application which is workign fine. I am now trying to persuade the queue trigger to only process one item at a time. My host.json is set up correctly, I think:
But when I run the app (either in Azure as a web job, or locally in Visual Studio), I see this:
I suspect that I am missing something really obvious, so wondering whether anyone has come across this before. I have found a few articles, but nothing that gives me any insight into what I am doing wrong.
Adding the contents of program.cs. I have tried adding "host.json" after the AddAzureAppConfiguration entry, but that makes no difference.
class Program
{
static async Task Main()
{
//var builder = new HostBuilder();
var builder = Host.CreateDefaultBuilder();
builder.ConfigureLogging((context, a) =>
{
a.AddConsole();
});
builder.ConfigureAppConfiguration((hostContext, config) =>
{
config.AddUserSecrets(
"5aa19112-5ff7-467b-b062-f37c3654872d"); // This is automatic for a web app, but not for a console app
var settings = config.Build();
var connectionString = settings.GetConnectionString("AzureAppConfiguration");
config.AddAzureAppConfiguration(connectionString);
});
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
builder.ConfigureServices((hostContext, services) =>
{
services.AddMemoryCache();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
}

I think you are using the Azure WebJobs SDK v3.x. In v3.x, hosts.json does not work for WebJob.
Instead, version 3.x uses the standard ASP.NET Core APIs, so you need to configure it using the ConfigureWebJobs method:
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage(a => {
a.BatchSize = 8;
a.NewBatchThreshold = 4;
a.MaxDequeueCount = 4;
a.MaxPollingInterval = TimeSpan.FromSeconds(15);
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
Docs: https://learn.microsoft.com/pt-pt/azure/app-service/webjobs-sdk-how-to#queue-storage-trigger-configuration

Related

.net core 6 jwt token mocking

I am looking for a tutorial on how to mock authentication tokens for .net core 6 web services. Some years ago, at a previous job, I looked up how to do this with .net 3 and got it to work. But 6 removed the startup.cs file and seems to have shifted things around quite a bit. There are very few examples of doing this for 6.
I am in the process of creating a series of unit tests for the endpoints in a new web application. I am starting over from bare bones. Here is the code example. I know that it is possible to recreate the Startup.cs file, but for the time being I would prefer to do it without that. Are there any examples of this for a .net 6 specific architecture?
internal class DssiApiTest : WebApplicationFactory<Program>
{
private readonly string _environment;
public DssiApiTest(string environment = "Development")
{
_environment = environment;
}
protected override IHost CreateHost(IHostBuilder builder)
{
builder.UseEnvironment(_environment);
var settings = new ApiSettings();
// Add mock/test services to the builder here
builder.ConfigureServices(services =>
{
services.AddScoped(sp =>
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase("Tests")
.UseApplicationServiceProvider(sp)
.Options;
using (var context = new ApplicationDbContext(options,
MakeMockTenantService(),
(Microsoft.Extensions.Options.IOptions<ApiSettings>)settings))
{
context.PartCustomers.Add(CreatePartCustomer(1, 1));
context.PartCustomers.Add(CreatePartCustomer(2, 1));
context.SaveChanges();
}
// Replace SQLite with in-memory database for tests
return options;
});
});
return base.CreateHost(builder);
}
}
I think I found the answer to what I needed to do. I have not been able to fully test it yet, however, because I am running into another issue that is throwing an error. Will have to ask another question for that one. Here is what I have so far. If anyone can elaborate or correct this please feel free to do so. Like I said, I have not fully tested it and don't want to lead others astray. Will update once I have it worked out.
I added a new TestAuthHandler to the virtual client that returns a mock auth result like so :
using var application = new TestWebApplicationFactory();
var client = application.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
"Test", options => { });
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Test");
Here is the code for the TestAuthHandler
public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public TestAuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var claims = new[] { new Claim(ClaimTypes.Name, "Test user") };
var identity = new ClaimsIdentity(claims, "Test");
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "Test");
var result = AuthenticateResult.Success(ticket);
return Task.FromResult(result);
}
}

Loopback: How to stop a console command?

I am running a loopback command through the command line.
the script is as follows:
const app = require('../../server/server');
let acquireToken = function() {
app.stop();
};
acquireToken();
However this does not seem to work as stop() is not a function. So I have added this in the server.js file:
'use strict';
let loopback = require('loopback');
let boot = require('loopback-boot');
let app = module.exports = loopback();
let winston = require('./winston');
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
let baseUrl = app.get('url').replace(/\/$/, '');
winston.info('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
let explorerPath = app.get('loopback-component-explorer').mountPath;
winston.info('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
let server;
app.stop = () => {
server.close();
}
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
server = app.start();
});
module.exports = app;
But require.main == module is preventing this from working as this gives me the following:
TypeError: Cannot read property 'close' of undefined
What is the recommended way of making this work?
Your question is a bit misleading because you're trying to stop an express object returned from a require call, so a more accurate question is
How do I start and stop a listening loopback app from another script?
In server.js change app.start = function() to app.start = function(cb) and add if (cb) {cb()}; to the end.
'use strict';
let loopback = require('loopback');
let boot = require('loopback-boot');
let app = module.exports = loopback();
let winston = require('./winston');
app.start = function(cb) {
// start the web server
return app.listen(function() {
app.emit('started');
let baseUrl = app.get('url').replace(/\/$/, '');
winston.info('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
let explorerPath = app.get('loopback-component-explorer').mountPath;
winston.info('Browse your REST API at %s%s', baseUrl, explorerPath);
}
if (cb) cb();
});
};
let server;
app.stop = () => {
server.close();
}
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
server = app.start();
});
module.exports = app;
And for your file which starts and stops loopback
// Setup loopback, but don't start the server
const app = require('./server');
// Define our callback function
let acquireToken = function() {
app.server.close();
console.log('closed');
};
// Hold onto the listener object so we can stop it later and start the server with the callback which executes after startup.
app.server = app.start(acquireToken);

Run Amazon Alexa Skill locally instead of AWS Lambda (Javascript)

Is it possible to run alexa skill locally with ngrok instead AWS? I built a skill in AWS Lambda but I would rather use my own server. What can I do to run Alexa locally?
I tried https://github.com/alexa-js/alexa-app-server but it makes any sense because I would need to rewrite my whole code :( The better solution is http://docs.bespoken.tools/en/latest/tutorials/tutorial_lambda_nodejs/ but it isn't the best. It just works only for a wellcome intent and freezes after that :(
Terminal Logs from bespken command:
BST: v0.9.35 Node: v7.8.0
Your URL for Alexa Skill configuration:
https://proxy.bespoken.tools?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d
INFO 2017-04-25T20:27:20.628Z Connected - proxy.bespoken.tools:5000
INFO 2017-04-25T20:27:26.812Z RequestReceived: POST /?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d ID: 1493152039146
INFO 2017-04-25T20:27:26.815Z Forwarding localhost:10000
Current hour: 24
Warning: Application ID is not set
INFO 2017-04-25T20:27:27.939Z ResponseReceived ID: 1493152039146
INFO 2017-04-25T20:28:10.755Z RequestReceived: POST /?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d ID: 1493152078963
INFO 2017-04-25T20:28:10.756Z Forwarding localhost:10000
Warning: Application ID is not set
INFO 2017-04-25T20:28:11.157Z ResponseReceived ID: 1493152078963
INFO 2017-04-25T20:28:51.073Z RequestReceived: POST /?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d ID: 1493152113739
INFO 2017-04-25T20:28:51.073Z Forwarding localhost:10000
Warning: Application ID is not set
INFO 2017-04-25T20:28:51.995Z ResponseReceived ID: 1493152113739
Yes, there are several solutions for running your node lambda locally. I've been using node-lambda, for example. Like most solutions it is oriented to users who want to test locally and then easily deploy to AWS Lambda.
If you want to run them yourself, I would note that MS and IBM have made their implementations of lambda open-source (here's MS's and IBM's). I haven't actually tried it myself, and I would note that with AWS, GCP, and Azure all providing Lambda services for node the market for these is healthy and the lock-in is minimal so I feel less need to be able to run it myself than for something like Dynamo.
But I also recommend that you continue to pursue BST. I'm using some of my own pieces for testing my skills because I got started before I heard of their stuff, but what I have tried of their's (BSTAlexa) is very useful and I see that they provide some of the other pieces you need for easy and effective testing of your skill.
Here's some sample code that you can use to easily run a Lambda locally, call this file AlexaLambda.js:
const log = require('console');
var AWS = require('aws-sdk');
AWS.config.region = "us-east-1";
AWS.config.update({
accessKeyId: "----",
secretAccessKey: "----",
});
/**
* Wraps the actual underlying Alexa lambda initialization in a
* Promise. Injects test mocks where appropriate.
*/
var initializerPromise = new Promise(function(fulfill, reject) {
// Mock out certain imports here if you want but not necessary
/*
var Module = require('module');
var originalRequire = Module.prototype.require;
Module.prototype.require = function() {
if ((arguments[0] == 'S3FeedService') ||
(arguments[0] == './lib/S3FeedService')) {
return MockS3Service;
} else if ((arguments[0] == 'WebsocketService') ||
(arguments[0] == './lib/WebsocketService')) {
return WSMockService;
} else if ((arguments[0] == 'SQSService') ||
(arguments[0] == './lib/SQSService')) {
return SQSMockService;
} else {
return originalRequire.apply(this, arguments);
}
};*/
// Import your actual lambda here.
var lambda = require('../src/index.js');
fulfill(lambda);
});
/**
* The Alexa Lambda context object which is called upon completion
* of lambda execution. Also wraps the callback which contains the
* test assertion code of the caller.
* #param callback - must be of the form function(error, result) {};
* #returns
*/
function Context(callback) {
this.clientContext = {"env": {}};
this.callback = callback;
}
Context.prototype.done = function(error, result) {
if (typeof error != "undefined" && error) {
this.callback(error, null);
} else {
this.callback(null, result);
}
}
Context.prototype.succeed = function(result) {
this.callback(null, result);
}
Context.prototype.fail = function(error) {
this.callback(error, null);
}
/**
* The AlexaLambda object that's exposed for test cases.
* #returns
*/
function AlexaLambda() {
}
/**
* Executes the lambda function, provided an inputEvent and a
* callback.
* #param inputEvent - the input event that includes the intent.
* #param callback - called upon completion of lambda execution.
*/
AlexaLambda.prototype.execute = function(inputEvent, callback) {
initializerPromise.then(function(lambda) {
var context = new Context(callback);
lambda.handler(inputEvent, context);
});
}
/**
* Export the lambda class, importers instantiate via new AlexaLambda();
*/
module.exports = AlexaLambda;
Then you can use this 'AlexaLambda' in your tests like so (in my case, I'm using Mocha):
var AlexaLambda = require('./AlexaLambda');
var Event = require('./Event'); // My 'fake' Event class
describe("Guest User Test", function() {
var alexaLambda = new AlexaLambda();
it("Alexa, open/launch 60db", function(done) {
var event = Event.createLaunchEvent();
alexaLambda.execute(event, function(error, result) {
validateYourResultHere();
done();
})
});
Then it's just a matter of running your test via whatever framework you're using.
You can test your alexa skill locally by following the following tutorial:
How to test Alexa locally

Owin.TestServer To Test a Middleware that Requires Authentication

I have a middleware method that requires context.Authentication.User.Identity.Name to be resolved for proper execution. However, when writing a unit test these properties are obviously null as no sign-in has occurred. I am not using Oauth or anything authentication related in this middleware (beyond the obvious name property), as it should be handled elsewhere in another middleware (to promote re-use/flexibility of the component I am developing). Is there a way to mock/fake this value so I can run my test? I have tried everything I can think of to fake a sign-on and I am just stuck at this point. To be clear the middleware needs the value not a webapi call or the like.
//Arrange
var resolver = A.Fake<IDependencyResolver>();
A.CallTo(() => resolver.GetService(typeof(ISomeService))).Returns(new TestService());
using (var server = TestServer.Create(app =>
{
app.UseMyMiddleware(new MyMiddlewareOptions()
{
DependencyResolver = resolver
});
app.Run(async ctx =>
{
await ctx.Response.WriteAsync(ctx.Request.Path.Value);
});
}))
{
//Act
var response = await server.CreateRequest("/").GetAsync();
//Assert
A.CallTo(() => resolver.GetService(typeof(ISomeService)))
.MustHaveHappened(Repeated.Exactly.Once);
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
//Etc.
}
So here is one way I suppose not thrilled with it but it does the job. I will wait to accept as I imagine there should be a better way.
public class TestFakeLoginMiddleware : OwinMiddleware
{
public TestFakeLoginMiddleware(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
var identity = A.Fake<IIdentity>();
A.CallTo(() => identity.Name).Returns("TEST#domain.local");
var user = new ClaimsPrincipal(identity);
context.Request.Context.Authentication.User = user;
await Next.Invoke(context);
}
}
A bit late, I know, but could you not just create a new ClaimsIdentity?
public override async Task Invoke(IOwinContext context)
{
var identity= new ClaimsIdentity(new List<Claim> {
new Claim(ClaimTypes.Name, "TEST#domain.local")
});
var user = new ClaimsPrincipal(identity);
context.Request.Context.Authentication.User = user;
await Next.Invoke(context);
}

How to test web components in Dart?

There isn't much documentation insofar on web-ui testing in Dart. Two methods are available : a) run through Chrome's DumpRenderTree or b) a trick that consists of loading the app as is and running the test code on top of it. For trivial cases, the first option seems to be a bit tedious. So the latter option -- which in my case, doesn't work when it comes to load components.
With the following file structure:
test/
main_test.html
main_test.dart
web/
main.html
app.html
(all the files are listed in this gist)
The following test set hangs on the second step.
main() {
useShadowDom = true;
test('Inline element is initially present.', () {
var story = () => expect(query('#hdr'), isNotNull);
Timer.run(expectAsync0(story));
});
test('Component is loaded.', () {
var story = () => expect(query('#globe'), isNotNull);
Timer.run(expectAsync0(story));
});
}
How could the app component be loaded? More broadly, is there another method of testing web components?
For web-ui test you have to query the shadow dom or the xtag (this) of the webcomponent that you whant to test instead of the "classic" dom.
Based on TodoMVC code sample
With your code:
A working version of this test is :
main() {
useShadowDom = true;
test('Inline element is initially present.', () {
var story = () => expect(query('#hdr'), isNotNull);
Timer.run(expectAsync0(story));
});
test('Component is loaded.', () {
var root = query("span[is=x-app]").shadowRoot;
var story = () => expect(root.query('#globe'), isNotNull);
Timer.run(expectAsync0(story));
});
}
and a test version without expectAsync should be:
main() {
useShadowDom = true;
Timer.run(() {
test('Header element is initially present.', () {
var hdr = query('#hdr');
expect(hdr, isNotNull);
});
test('EchapApp component is loaded.', () {
var root = query("span[is=x-app]").shadowRoot;
var globe = root.query('#globe');
expect(globe, isNotNull);
});
});
}
and finaly a version without shadow dom :
main() {
//useShadowDom = true;
Timer.run(() {
test('Header element is initially present.', () {
var hdr = query('#hdr');
expect(hdr, isNotNull);
});
test('EchapApp component is loaded.', () {
var root = query("span[is=x-app]").xtag;
var globe = root.query('#globe');
expect(globe, isNotNull);
});
});
}
For me this 3 codes are 100% pass on Dartium with
Dart Editor version 0.5.20_r24275
Dart SDK version 0.5.20.4_r24275
You can try using the karma-dart runner: https://github.com/karma-runner/karma-dart
It even has a web components example.
library click_counter_test;
import 'package:unittest/unittest.dart';
import 'dart:html';
import '../web/out/xclickcounter.dart';
main() {
test('CounterComponent.increment', () {
var hello = new DivElement();
var component = new CounterComponent.forElement(hello);
expect(component.count, equals(0));
component.increment();
expect(component.count, equals(1));
});
}
Although it is not Dart specific, you can use Selenium for testing the UI. I believe some members of the Dart team have used Selenium as well to do UI testing.