简体   繁体   中英

Change Environment Variables During Perl Unit Testing

I am trying to write some unit tests for this perl module function, but am having some issues with environment variables. I'll list the files first, then explain the issue in greater detail.

processBuildSubs.pm

package processBuildSubs;
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common;
use HTTP::Status;

# Declare environment variables used in this package that are needed
use constant URI_BASE     => $ENV {"URI_BASE"};
use constant URI_RESOURCE => $ENV {"URI_RESOURCE"};

# Shell Environment Related Constants visible.
# Make visible.

our $URI_BASE = URI_BASE;
our $URI_RESOURCE = URI_RESOURCE;

sub populatePartitions
{
  # Define locals
  my $url;
  my $ua = new LWP::UserAgent;

  $url = "$URI_BASE"."$URI_RESOURCE"."/some/path";

  # Make a request to the $url
  $res = $ua->request (GET $url);

  if ($res->code() != HTTP::Status->RC_OK() )
  {
     # The request didn't return 200 OK so it's in here now.
  }
  else
  {
     # The request returned 200 OK, so now it's here.
  }
}

I want to be able to unit test both the if path and the else path , however, it would be best for me if I don't need to change the processBuildSubs.pm code at all. It's an external file that I don't currently have control over. I am just tasked in unit testing it (although I do understand it could be tested more efficiently if we could also change the source code).

So in order to test both paths, we need the environment variables URI_BASE and URI_RESOURCE to be set accordingly, so that the request fails once, and succeeds another time. (I am interested in learning how to stub out this call at a future time, but that's reserved for another question.)

Here's my test file:

processBuildSubs.t

use strict;
use Test::More qw(no_plan);

BEGIN { use_ok('processBuildSubs') };

# Test 1 of populatePartitions() function
my $processBuildProdsCall = processBuildSubs::populatePartitions();
is( $populatePartitionsCall, 0, "populatePartitions() Test for 0 Val Passed" );

# Test 2 of populatePartitions() function
# I need to change some environment variables that processBuildSubs depends on here.
my $processBuildProdsCall = processBuildSubs::populatePartitions();
is( $populatePartitionsCall, 0, "populatePartitions() Test for 0 Val Passed" );

The best attempt we have right now at changing the environment variables is using an external shell script like so (But it would be ideal to change them between the my calls in the file above):

run_tests.sh

#!/bin/bash

# Run the tests once
perl ./BuildProcess.pl
perl ./Build testcover  # Ultimately calls the processBuildSubs.t test file

# Now export some variables so the other test passes.
export URI_BASE="https://some-alias/"
export URI_RESOURCE="some-resource"

# Then run the test suite again with the env set so the else condition passes.
perl ./BuildProcess.pl
perl ./Build testcover

As you can see, this would be a bad way of doing things, as we run the entire test suite with different environments each time. Ideally we'd like to setup our environment in the processBuildSubs.t file if possible, between tests.

Please let me know if I can provide any further information.

Are you averse to having separate scripts for separate test environments?

# processBuildSubs.t
BEGIN {
   @ENV{"URI_BASE","URI_RESOURCE"} = ("https://some-alias/","some-resource");
}
use Test::More;
... tests go here ...

# processBuildSubs-env2.t
BEGIN {
   @ENV{"URI_BASE","URI_RESOURCE"} = ("https://another-alias/","another-resource");
}
use Test::More;
... tests go here ...

By setting %ENV in a BEGIN block, before any other modules are loaded, you make the different environment variables available to your other modules at compile-time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM