简体   繁体   中英

How to configure a Spring @Component differently when testing

I am trying to learn Spring by writing an app which queries information from 2 LDAP sources via 2 Service classes.

I have an ActiveDirectory source:

@Component
public class AdLdapService implements LdapService {
    @Override
    public Optional<LdapMember> getUserById(String accountName) throws Exception {
    }
}

and this is configured using

@Configuration
public class AdLdapConfiguration {

    @Autowired
    Environment env;

    @Bean("ad-context")
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        contextSource.setUrl(env.getRequiredProperty("ldap.ad.url"));
        contextSource.setBase(env.getRequiredProperty("ldap.ad.base"));
        contextSource.setUserDn(env.getRequiredProperty("ldap.ad.user"));
        contextSource.setPassword(env.getRequiredProperty("ldap.ad.password"));
        return contextSource;
    }

    @Bean("ad-template")
    public LdapTemplate ldapTemplate() {
        return new LdapTemplate(contextSource());
    }
}

I also have a second pair of classes for accessing a different LDAP source. This all works fine.

Now I want to add some unit tests to test the 2 services and, rather than using a live LDAP, I thought it would be better to create a small embedded LDAP on the fly and test against that. This is where I've got stuck.

I want to create 2 separate LDAPs and populate them from 2 LDIF files. My 2 LdapService implementations should then link to the relevant embedded LDAPs.

My Spring knowledge is still very limited and I don't know the elegant way to set this up.

You can start off with a test that will load the application context with the configuration of your choice:

@RunWith(SpringRunner.class)
@ContextConfiguration(...<YOUR_CONFIG_GOES_HERE>)
public void MySampleLdapTest {

    @Autowired
    public LdapTemplate testTemplate;

    @Test
    public void testLdap() {
      testTemplate.doWhateverYouNeedAndVerifyTheResult();
    }
}

Now if you need to run the Ldap Service in-memory its certainly an integration test. You can do one of the following:

  1. Use TestContainers framework to fire up the Ldap Service Docker image and interact with it.
  2. Find some in-memory implementation of Ldap Server and integrate with the test.
  3. Use @MockBean annotation if you want to mock a bean that interacts with the LdapService but you still want to load the application context with a bunch of your beans. This is a special annotation that alters the application context : if there was a bean of that type - it will place a mock onto the application context instead (a regular mock created with mockito), if there was no bean at all - it will create the mock and add one to the app context anyway.

Last but not the least, all these tests are significantly slower than a regular mockito style unit testing. In general spring tests is a wonderful tool but its for integration tests, not for unit tests. If you can do a unit test without spring at all with mockito - it can be even a better choice.

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