[389-devel] Proof of concept: mocking DS in lib389

Rich Megginson rmeggins at redhat.com
Fri Oct 25 21:00:13 UTC 2013


On 10/25/2013 01:36 PM, Jan Rusnacko wrote:
> Hello Roberto and Thierry,
>
> as I promised, I am sending you a proof-of-concept code that demonstrates, how
> we can mock DS in unit tests for library function (see attachment). You can run
> tests just by executing py.test in tests directory.
>
> Only 3 files are of interest here:
>
> lib389/dsmodules/repl.py - this is a Python module with functions - they expect
> DS instance as the first argument. Since they are functions, not methods, I can
> just mock DS and pass that fake one as the first argument to them in unit tests.
>
> tests/test_dsmodules/conftest.py - this file contains definition of mock DS
> class along with py.test fixture, that returns it.
>
> tests/test_dsmodules/test_repl.py - this contains unit tests for functions from
> repl.py.
>
> What I do is quite simple - I override ldapadd, ldapdelete .. methods of mock DS
> class, so that instead of sending command to real DS instance, they just store
> the data in 'dit' dictionary (which represents content stored in DS). This way,
> I can check that when I call e.g. function enable_changelog(..), in the end DS
> will have correct changelog entry.
>
> To put it very bluntly - enable_changelog(..) function just adds correct
> changelog entry to whatever is passed to it as the first argument. In unit
> tests, it is mock DS, otherwise it would be real DS class that sends real ldap
> commands to real DS instance behind.
def test_add_repl_manager(fake_ds_inst_with_repl):
     ds_inst = fake_ds_inst_with_repl
     ds_inst.repl.add_repl_manager("cn=replication manager, cn=config", 
"Secret123")
     assert ds_inst.dit["cn=replication manager, 
cn=config"]["userPassword"] == "Secret123"
     assert ds_inst.dit["cn=replication manager, 
cn=config"]["nsIdleTimeout"] == "0"
     assert ds_inst.dit["cn=replication manager, cn=config"]["cn"] == 
"replication manager"

If you are using a real directory server instance, doing 
add_repl_manager() is going to make a real LDAP ADD request, right? Will 
it still update the ds_inst.dit dict?  Wouldn't you have to do a real 
LDAP Search request to get the actual values?

>
> Now I can successfully test that enable_changelog really works, without going
> into trouble defining DSInstance or ldap calls at all. Also, I believe this
> approach would work for 95% of all functions in lib389. Another benefit is that
> unit tests are much faster, than on real DS instance.
>
> Sidenote: even though everything is defined in separate namespace of 'repl'
> module as function, in runtime they can be used as normal methods of class
> DSInstance. That is handled by DSModuleProxy. We already went through this, but
> not with Roberto.
>
> Hopefully, now with some code in our hands, we will be able to understand each
> other on this 'mocking' issue and come to conclusions more quickly.
>
> Let me know what you think.
>
> Thank you,
> Jan



More information about the 389-devel mailing list