【问题标题】:Spring Ldap unit testing with custom schema definition使用自定义模式定义进行 Spring Ldap 单元测试
【发布时间】:2015-02-16 07:41:43
【问题描述】:

我正在尝试使用 Spring Ldap 设置嵌入式 ldap 以进行单元测试。但我需要为自定义对象类/属性定义使用自定义模式。如何使用 Spring Ldap 测试配置它 (LdapTestUtils?)

实际上,如果我运行测试,它会说我的自定义对象类“myOb”未在架构中定义,并显示以下消息:

org.springframework.ldap.UncategorizedLdapException: Failed to populate LDIF; nested exception is javax.naming.directory.NoSuchAttributeException: [LDAP: error code 16 - NO_SUCH_ATTRIBUTE: failed for     Add Request :
...
: OID for name 'myOb' was not found within the OID registry]; remaining name 'cn=123456, ou=MyUser, o=company.com'

如果我从 ldif 评论 objectClass: myOb,则测试失败并返回空值(未读取属性)。

这是我的测试课:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = LdapConfiguration.class, loader = AnnotationConfigContextLoader.class)
public class LdapTest {

    // Ldap port
    private static final int LDAP_PORT = 18880;

    // Base DN for test data
    private static final LdapName baseName = LdapUtils.newLdapName("o=company.com");

    @Autowired
    LdapTemplate ldapTemplate;

    @BeforeClass
    public static void setupBeforeClass() {
        LdapTestUtils.startEmbeddedServer(LDAP_PORT, baseName.toString(), "ldaptest");
        // How to load schema definition ?
    }

    @AfterClass
    public static void teardownAfterClass() throws Exception {
        LdapTestUtils.shutdownEmbeddedServer();
    }

    @Before
    public void setup() throws Exception {
        LdapTestUtils.cleanAndSetup(ldapTemplate.getContextSource(), baseName, new ClassPathResource("ldap/test-users.ldif"));
    }


    @Test
    public void testSearchLdap() throws Exception {     
        String myObId = ldapTemplate.lookup(LdapNameBuilder.newInstance("ou=MyUser, o=company.com").add("cn", "123456").build(), new AbstractContextMapper<String>() {
            @Override
            protected String doMapFromContext(DirContextOperations ctx) {
                return ctx.getStringAttribute("myObId"); // custom type
            }           
        });
        Assert.assertNotNull(myObId); // myObId is null if I comment `objectClass: myOb` !
    }
}

还有我的 ldif:

dn: ou=MyUser, o=company.com
ou: User
description: MyUser
objectClass: top
objectClass: organizationalunit

dn: cn=123456, ou=MyUser, o=company.com
objectClass: top
objectClass: person
objectClass: myOb
cn: 123456
sn: 823456
myObId: TEST

【问题讨论】:

  • 嗨,我也面临同样的问题。您是否设法解决了它,还是最终使用了下面建议的解决方法?
  • 是的,我正在使用下面建议的InMemoryDirectoryServer 服务器解决方案
  • 好的,谢谢,看来我也得这么做了……

标签: java spring unit-testing ldap spring-ldap


【解决方案1】:

我不知道如何使用 Spring Ldap... 但我在单元测试中使用 Unboundid InMemoryDirectoryServer。服务器的这种实现不限制任何自定义对象类/属性定义。 如果你愿意,我可以在这里分享我的 JUnitRule。该规则启动 InMemory 服务器并将 ldiff 加载到其中

更新:

public class LdapServerRule extends ExternalResource {
private static final Log LOG = LogFactory
        .getLog(LdapServerRule.class);

public static final String DefaultDn = "cn=Directory Manager";
public static final String DefaultPassword = "password";
private String baseDn;
private String dn;
private String password;
private String lDiffPath;
private InMemoryDirectoryServer server;
private int listenPort;

public LdapServerRule(String baseDn, String lDiffPath) {
    this(baseDn, lDiffPath, 0);
}


public LdapServerRule(String baseDn, String lDiffPath, int listenPort) {
    this.lDiffPath = lDiffPath;
    this.baseDn = baseDn;
    this.dn = DefaultDn;
    this.password = DefaultPassword;
    this.listenPort = listenPort;

}

@Override
protected void before() {
    start();
}

@Override
protected void after() {
    stop();
}

public int getRunningPort() {
    return getServer().getListenPort();
}

private void start() {
    InMemoryDirectoryServerConfig config;

    try {
        LOG.info("LDAP server " + toString() + " starting...");
        config = new InMemoryDirectoryServerConfig(getBaseDn());
        config.addAdditionalBindCredentials(getDn(),
                getPassword());
        config.setSchema(null);
        config.setListenerConfigs(
                InMemoryListenerConfig.createLDAPConfig("LDAP", getListenPort()));
        setServer(new InMemoryDirectoryServer(config));

        getServer().importFromLDIF(true, getLDiffPath());
        getServer().startListening();
        LOG.info("LDAP server " + toString() + " started. Listen on port " + getServer().getListenPort());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

}

private void stop() {
    server.shutDown(true);
    LOG.info("LDAP server " + toString() + " stopped");
}

public String getBaseDn() {
    return baseDn;
}

public String getDn() {
    return dn;
}

public String getPassword() {
    return password;
}

public InMemoryDirectoryServer getServer() {
    return server;
}

public void setServer(InMemoryDirectoryServer server) {
    this.server = server;
}

public String getLDiffPath() {
    return lDiffPath;
}

public int getListenPort() {
    return listenPort;
}

@Override
public String toString() {
    return com.google.common.base.Objects.toStringHelper(this)
            .add("baseDn", baseDn)
            .add("listenPort", listenPort)
            .toString();
}

}

你可以这样使用这条规则

@ClassRule
public static final LdapServerRule LDAP_RULE =
        new LdapServerRule("dc=mmkauth", resourceFilePath("data.ldiff"));

LDAP_RULE.getListenPort() 返回实际的连接端口,或者你可以将端口直接传递给构造函数

【讨论】:

  • LdapTestUtils 使用 ApacheDS。我对您的单元测试规则非常感兴趣,因为您在内存目录服务器中!可以分享一下吗?
  • InMemoryDirectoryServer 的任何 maven 依赖项?编辑:找到mvnrepository.com/artifact/com.unboundid/unboundid-ldapsdk
  • @Aure77 如果您想在每次测试前重新加载 ldiff,请使用 @Rule 而不是 @ClassRule
  • 感谢您的规则,我会尽快测试。
【解决方案2】:

Spring Boot 提供了两个属性来忽略架构或设置架构文件的路径:

spring.ldap.embedded.validation.enabled=true # Whether to enable LDAP schema validation.
spring.ldap.embedded.validation.schema= # Path to the custom schema.

@见common-application-properties

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 2018-05-27
    相关资源
    最近更新 更多