Your mother was X.500 and your father smells of RFCs! Now go away or I shall mock you a second time!
  - from the original draft of Monty Python and the Holy Grail.

I finally buckled down and starting to mock the LDAP server in my tests rather than trying to connect to a live server. Other than the documentation, there's not a lot of examples out there for Test::Net::LDAP::Mock or Test::Net::LDAP::Util, so here's the results from banging away at it for an afternoon along with what I think is going on. Please feel free to point out what I've done wrong. I've stopped where it started working for me.

I have a Mojolcious app that authenticates against LDAP, but the tests would fail when using dummy accounts or when I wasn't connected. Here's the test I wrote

use Mojo::Base -strict; use Test::More; use Test::Mojo; use Test::Net::LDAP::Util qw/ldap_mockify/; my $t = Test::Mojo->new('MyApp'); my $basedn = 'dc=ldap,dc=perl,dc=org'; ldap_mockify { # mock the LDAP server and add entries my $ldap = Net::LDAP->new('ldap.example.com'); $ldap->add("uid=good,$basedn", attrs => [ userid => 'whitecamel']) +; $ldap->add("uid=evil,$basedn", attrs => [ userid => 'blackperl']); $ldap->mock_bind(sub { my $arg = shift; if ($arg->{dn}->dn() eq "uid=good,$basedn" && $arg->{password} eq 'LetMeIn' ) { return Net::LDAP::Constant::LDAP_SUCCESS; } else { return Net::LDAP::Constant::LDAP_INVALID_CREDENTIALS; } } ); # test the app $t->post_ok('/login' => {Accept => '*/*'} => form => {username => 'rubyred', password => 'nosuchuser'} ) ->status_is(403, 'User not found in LDAP'); $t->post_ok('/login' => {Accept => '*/*'} => form => {username => 'blackperl', password => 'Arrrgh'}) ->status_is(403, 'No access for incorrect password'); $t->post_ok('/login' => {Accept => '*/*'} => form => {username => 'whitecamel', password => 'wrongpassword'}) ->status_is(403, 'No access for incorrect password'); $t->get_ok('/secure/protected') ->status_is(401, 'Protected page is inaccessible without correct login'); $t->post_ok('/login' => {Accept => '*/*'} => form => {username => 'whitecamel', password => 'LetMeIn'} ) ->status_is(302, 'Redirected to Welcome page on successful login') ->content_like(qr/Welcome/); $t->get_ok('/secure/protected') ->status_is(200) ->content_like(qr/This is a protected page/, 'Protected page now accessible'); }; done_testing();

Steps to mocking

Setup your test environment as usual and use Test::Net::LDAP::Util qw/ldap_mockify/; The ldap_mockify method intercepts all calls to Net::LDAP->new() and redirects them to your mocked LDAP directory.
  1. Create a new Net::LDAP object
  2. Use the object to populate your mocked server with data using the add method
  3. If you want to mock the authentication process, use the mock_bind method with a call back that returns LDAP_SUCCESS or LDAP_INVALID_CREDENTIALS
  4. Now that your LDAP server is all mocked up, run your tests
  5. Don't forget the }; at the end of the method. It's a funny error message when you forget the semicolon at the end.

Notes

Well, what do you think? Does it get the job done?

Edit - while cleaning up tabs used for putting this post together, I found a relevant question on StackOverflow from 5 years ago, but it hasn't been answered so far.

Ea

Sometimes I can think of 6 impossible LDAP attributes before breakfast.

YAPC::Europe::2018 — Hmmm, need to talk to work about sending me there or to Mojoconf.


In reply to Mocking LDAP in your tests by Ea

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.