mikkoi has asked for the wisdom of the Perl Monks concerning the following question:

I have a Dancer2 app.
I want to test it properly against a database.
For every test run I create a new database and a new empty schema (PostgreSQL).
My new database has a random name (e.g. app_123abc) and at the end of the test I drop the database.

How can I change the Dancer2 app configuration during the test run, or before I do my $test = Plack::Test->create( $app );?
As it is, is just loads the config files for development. I want to provide my own configuration programmatically. Creating files in the current directory is not an option.

I have tried
config->{'my_stuff'} = \%my_stuff
set 'my_stuff' => \%my_stuff but Dancer2 doesn't seems to pick it up or it gets overwritten later by the config from the files.

Update:

Example

#!/perl ## no critic (Modules::ProhibitMultiplePackages) use strict; use warnings; use 5.014; # JSON::PP included in CORE. package ConfigChangeTest; use Dancer2; set serializer => 'JSON'; get qr{/info}msx => sub { return { appname => config->{'appname'}, }; }; package main; use Test2::V0 -srand => time, qw(:DEFAULT); use Plack::Test; use HTTP::Request; use JSON; use Dancer2; my $appname = 'ConfigChangeTest'; set appname => $appname; my $test = Plack::Test->create( ConfigChangeTest->to_app ); my $req = HTTP::Request->new( GET => '/api/1/info' ); my $res = $test->request( $req ); ok( $res->is_success, 'Is success' ); # Fails! # appname is the one set in the file `environments/development.yml` or + file `config.yml`. is( decode_json $res->content, { appname => $appname, }, 'Is right con +tent' ); done_testing;

Replies are listed 'Best First'.
Re: Dancer2: Create a configuration for testing
by kcott (Archbishop) on Jan 06, 2021 at 05:47 UTC

    G'day mikkoi,

    [Disclaimer: I'm not a Dancer2 user; in fact, I needed to install it for the tests below. I just used available documentation for the code I wrote.]

    Dancer2::Core::Role::ConfigReader has:

    "... provides a setting() method which is supposed to be used by externals to read/write config entries."

    Running this (quick-and-dirty) script:

    #!/usr/bin/env perl use strict; use warnings; use Dancer2; get '/hello' => sub { return 'Hello, world!'; }; get '/my_stuff' => sub { my $my_stuff = setting('my_stuff') || {}; my $x = $my_stuff->{X} || 'not set'; my $y = $my_stuff->{Y} || 'not set'; return "X[$x] Y[$y]"; }; get '/my_new_stuff' => sub { setting('my_stuff' => {X => 'newX', Y => 'newY'}); return 'New stuff configured.'; }; dance;

    I was able to do:

    $ curl http://localhost:3000/hello Hello, world! $ curl http://localhost:3000/my_stuff X[not set] Y[not set] $ curl http://localhost:3000/my_new_stuff New stuff configured. $ curl http://localhost:3000/my_stuff X[newX] Y[newY]

    That seems to be the type of thing you're trying to do. Apologies in advance if I'm barking up the wrong tree.

    — Ken

      Nice demo Ken! Dancer is cool, isn't it?

      I think that the set keyword in the Dancer DSL is intended to be the user-called function that wraps the Role method. I updated your example to use

      set 'my_stuff' => {X => 'newX', Y => 'newY'};
      ... which is how I code my own D2 apps, as shown in the main doc, and it worked the same.

      Hope this helps!


      The way forward always starts with a minimal test.

        ++ Thanks for the generous feedback.

        As I indicated, that was my first Dancer2 code; although, I do have some minimal experience with Dancer, so it wasn't completely foreign to me. I appreciate the heads-up re set vs. setting.

        I did an additional test, using config and set (instead of the two setting() calls) and adding an actual config file.

        Code change:

        get '/my_stuff' => sub { my $my_stuff = config->{my_stuff} || {}; my $x = $my_stuff->{X} || 'not set'; my $y = $my_stuff->{Y} || 'not set'; return "X[$x] Y[$y]"; }; get '/my_new_stuff' => sub { set my_stuff => {X => 'newX', Y => 'newY'}; return 'New stuff configured.'; };

        New config file (in the same directory as the code):

        $ cat config.yml my_stuff: { X: 'oldX' }

        Test:

        $ curl http://localhost:3000/my_stuff X[oldX] Y[not set] $ curl http://localhost:3000/my_new_stuff New stuff configured. $ curl http://localhost:3000/my_stuff X[newX] Y[newY]

        I suspect that's a bit closer to what the OP wants: we'll have to wait and see.

        — Ken

Re: Dancer2: Create a configuration for testing
by 1nickt (Canon) on Jan 05, 2021 at 23:54 UTC

    Hi, you didn't post any code to review (please do), but generally, you read config with config; you set config with set.

    Hope this helps!


    The way forward always starts with a minimal test.

      Thanks. My bad. It should have created a minimum code sample. Updated now.

Re: Dancer2: Create a configuration for testing
by kcott (Archbishop) on Jan 06, 2021 at 13:23 UTC

    You have made a substantial change to your post which invalidates part of the first response you received: "... you didn't post any code ..." now appears to be an incorrect statement.

    Please clearly indicate updates to your post. See "How do I change/delete my post?" for details about this.

    — Ken