1Test::Net::LDAP::Mock(3U)ser Contributed Perl DocumentatiToenst::Net::LDAP::Mock(3)
2
3
4
6 Test::Net::LDAP::Mock - A mock LDAP client with simulated search in
7 memory
8
10 All the LDAP operations are performed in memory, instead of connecting
11 to the real LDAP server.
12
13 use Test::Net::LDAP::Mock;
14 my $ldap = Test::Net::LDAP::Mock->new();
15
16 "Test::Net::LDAP::Mock" is a subclass of Test::Net::LDAP, which is a
17 subclass of Net::LDAP.
18
19 In the actual test code, "ldap_mockify" in Test::Net::LDAP::Util should
20 be used to mock all the "Net::LDAP" instances in your application code.
21
22 use Test::More tests => 1;
23 use Test::Net::LDAP::Util qw(ldap_mockify);
24
25 ldap_mockify {
26 # Anywhere in this block, all the occurrences of Net::LDAP::new are
27 # replaced by Test::Net::LDAP::Mock::new
28 ok my_application_routine();
29 };
30
31 Note: if no LDAP entries have been added to the in-memory directory,
32 the "search" method will silently succeed with no entries found.
33
34 Below is an example to set up some fake data for particular test cases.
35
36 use Test::More tests => 1;
37 use Test::Net::LDAP::Util qw(ldap_mockify);
38
39 ldap_mockify {
40 my $ldap = Net::LDAP->new('ldap.example.com');
41
42 $ldap->add('uid=user1, ou=users, dc=example, dc=com');
43 $ldap->add('uid=user2, ou=users, dc=example, dc=com');
44 $ldap->add('cn=group1, ou=groups, dc=example, dc=com', attrs => [
45 member => [
46 'uid=user1, ou=users, dc=example, dc=com',
47 'uid=user2, ou=users, dc=example, dc=com',
48 ]
49 ]);
50
51 ok my_application_routine();
52 };
53
54 "Test::Net::LDAP::Mock" maintains a shared LDAP directory tree for the
55 same host/port, while it separates the directory trees for different
56 host/port combinations. Thus, it is important to specify a correct
57 server location consistently.
58
60 Overview
61 "Test::Net::LDAP::Mock" provides all the operations of "Net::LDAP",
62 while they are performed in memory with fake data that are set up just
63 for testing.
64
65 It is most useful for developers who write testing for an application
66 that uses LDAP search, while they do not have full control over the
67 organizational LDAP server. In many cases, developers do not have
68 write access to the LDAP data, and the organizational information
69 changes over time, which makes it difficult to write stable test cases
70 with LDAP. "Test::Net::LDAP::Mock" helps developers set up any fake
71 LDAP directory tree in memory, so that they can test sufficient
72 varieties of senarios for the application.
73
74 Without this module, an alternative way to test an application using
75 LDAP is to run a real server locally during testing. (See how
76 "Net::LDAP" is tested with a local OpenLDAP server.) However, it may
77 not be always trivial to set up such a server with correct
78 configurations and schemas, where this module makes testing easier.
79
80 LDAP Schema
81 In the current version, the LDAP schema is ignored when entries are
82 added or modified, although a schema can optionally be specified only
83 for the search filter matching (based on Net::LDAP::FilterMatch).
84
85 An advantage is that it is much easier to set up fake data with any
86 arbitrary LDAP attributes than to care about all the restrictions with
87 the schema. A disadvantage is that it cannot test schema-sensitive
88 cases.
89
90 Controls
91 LDAPv3 controls are not supported (yet). The "control" parameter given
92 as an argument of a method will be ignored.
93
95 new
96 Creates a new object. It does not connect to the real LDAP server.
97 Each object is associated with a shared LDAP data tree in memory,
98 depending on the target (host/port/path) and scheme (ldap/ldaps/ldapi).
99
100 Test::Net::LDAP::Mock->new();
101 Test::Net::LDAP::Mock->new('ldap.example.com', port => 3389);
102
103 mockify
104 Test::Net::LDAP::Mock->mockify(sub {
105 # CODE
106 });
107
108 Inside the code block (recursively), all the occurrences of
109 "Net::LDAP::new" are replaced by "Test::Net::LDAP::Mock::new".
110
111 Subclasses of "Net::LDAP" are also mockified. "Test::Net::LDAP::Mock"
112 is inserted into @ISA of each subclass, only within the context of
113 "mockify".
114
115 See also: "ldap_mockify" in Test::Net::LDAP::Util.
116
117 mock_data
118 Retrieves the currently associated data tree (for the internal purpose
119 only).
120
121 mock_schema
122 Gets or sets the LDAP schema (Net::LDAP::Schema object) for the
123 currently associated data tree.
124
125 In this version, the schema is used only for the search filter matching
126 (based on Net::LDAP::FilterMatch internally). It has no effect for any
127 modification operations such as "add", "modify", and "delete".
128
129 mock_root_dse
130 Gets or sets the root DSE (Net::LDAP::RootDSE) for the currently
131 associated data tree.
132
133 This should be set up as part of the test fixture before any successive
134 call to the root_dse() method, since Net::LDAP will cache the returned
135 object.
136
137 $ldap->mock_root_dse(
138 namingContexts => 'dc=example,dc=com'
139 );
140
141 Note: the namingContexts value has no effect on the restriction with
142 the topmost DN. In other words, even if namingContexts is set to
143 'dc=example,dc=com', the add() method still allows you to add an entry
144 to 'dc=somewhere-else'.
145
146 mock_bind
147 Gets or sets a LDAP result code (and optionally a message) that will be
148 used as a message returned by a later bind() call.
149
150 use Net::LDAP::Constant qw(LDAP_INVALID_CREDENTIALS);
151 $ldap->mock_bind(LDAP_INVALID_CREDENTIALS);
152 $ldap->mock_bind(LDAP_INVALID_CREDENTIALS, 'Login failed');
153 # ...
154 my $mesg = $ldap->bind(...);
155 $mesg->code && die $mesg->error; #=> die('Login failed')
156
157 In the list context, it returns an array of the code and message. In
158 the scalar context, it returns the code only.
159
160 Alternatively, this method can take a callback subroutine:
161
162 $ldap->mock_bind(sub {
163 my $arg = shift;
164 # Validate $arg->{dn} and $arg->{password}, etc.
165 if (...invalid credentials...) {
166 return LDAP_INVALID_CREDENTIALS;
167 }
168 });
169
170 The callback can return a single value as the LDAP result code or an
171 array in the form "($code, $message)". If the callback returns nothing
172 (or "undef"), it is regarded as "LDAP_SUCCESS".
173
174 mock_password
175 Gets or sets the password for the simple password authentication with
176 bind().
177
178 $ldap->mock_password('uid=test, dc=example, dc=com' => 'test_password');
179 # Caution: Passwords should usually *not* be hard-coded like this. Consider to load
180 # passwords from a config file, etc.
181
182 The passwords are stored with the entry node in the data tree.
183
184 Once this method is used, the bind() call will check the credentials
185 whenever the "password" parameter is passed. Anonymous binding and all
186 the other authentication methods are not affected.
187
188 mock_target
189 Gets or sets the target scheme://host:port to normalize the way for
190 successive "Test::Net::LDAP::Mock" objects to resolve the associated
191 data tree.
192
193 It is useful when normalizing the target scheme://host:port for
194 different combinations. For example, if there are sub-domains (such as
195 ldap1.example.com and ldap2.example.com) that share the same data tree,
196 the target host should be normalized to be the single master server
197 (such as ldap.example.com).
198
199 Test::Net::LDAP::Mock->mock_target('ldap.example.com');
200 Test::Net::LDAP::Mock->mock_target('ldap.example.com', port => 3389);
201 Test::Net::LDAP::Mock->mock_target(['ldap.example.com', {port => 3389}]);
202 Test::Net::LDAP::Mock->mock_target({scheme => 'ldaps', port => 3389});
203
204 Since this will affect all the successive calls to instantiate
205 "Test::Net::LDAP::Mock", it may not be ideal when your application uses
206 connections to multiple LDAP servers. In that case, you can specify a
207 callback that will be invoked each time a "Test::Net::LDAP::Mock"
208 object is instantiated.
209
210 Test::Net::LDAP::Mock->mock_target(sub {
211 my ($host, $arg) = @_;
212 # Normalize $host, $arg->{port}, and $arg->{scheme}
213 $host = 'ldap.example1.com' if $host =~ /\.example1\.com$/;
214 $host = 'ldap.example2.com' if $host =~ /\.example2\.com$/;
215 return ($host, $arg);
216 });
217
218 search
219 Searches for entries in the currently associated data tree.
220
221 $ldap->search(
222 base => 'dc=example, dc=com', scope => 'sub',
223 filter => '(cn=*)', attrs => ['uid', 'cn']
224 );
225
226 See "search" in Net::LDAP for more parameter usage.
227
228 compare
229 Compares an attribute/value pair with an entry in the currently
230 associated data tree.
231
232 $ldap->compare('uid=test, dc=example, dc=com',
233 attr => 'cn',
234 value => 'Test'
235 );
236
237 See "compare" in Net::LDAP for more parameter usage.
238
239 add
240 Adds an entry to the currently associated data tree.
241
242 $ldap->add('uid=test, dc=example, dc=com', attrs => [
243 cn => 'Test'
244 ]);
245
246 See "add" in Net::LDAP for more parameter usage.
247
248 modify
249 Modifies an entry in the currently associated data tree.
250
251 $ldap->modify('uid=test, dc=example, dc=com', add => [
252 cn => 'Test2'
253 ]);
254
255 See "modify" in Net::LDAP for more parameter usage.
256
257 delete
258 Deletes an entry from the currently associated data tree.
259
260 $ldap->delete('uid=test, dc=example, dc=com');
261
262 See "delete" in Net::LDAP for more parameter usage.
263
264 moddn
265 Modifies DN of an entry in the currently associated data tree.
266
267 $ldap->moddn('uid=test, dc=example, dc=com',
268 newrdn => 'uid=test2'
269 );
270
271 See "moddn" in Net::LDAP for more parameter usage.
272
273 bind
274 Returns an expected result message if the bind result has previously
275 been setup by the mock_bind() method. Otherwise, a success message is
276 returned.
277
278 unbind
279 Returns a success message.
280
281 abandon
282 Returns a success message.
283
284
285
286perl v5.36.0 2023-01-20 Test::Net::LDAP::Mock(3)