模拟 JNDI DNS 接口

mocking JNDI DNS interface

我有一个项目,我们使用 JNDI 来查询 DNS 记录。该项目本身运行良好,但是我找不到使用 jUnit 测试 JNDI 依赖组件的简单且独立的方法。

代码远非火箭科学,看起来很像典型的普通 JNDI DNS 请求。

目前我将测试单元指向 public DNS 记录(A、MX、TXT 记录),但这有点不行。

    ...
    Hashtable env = new Hashtable();
    env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
    env.put("com.sun.jndi.dns.timeout.initial", timeOut);
    env.put("com.sun.jndi.dns.timeout.retries", retries);
    env.put("java.naming.provider.url", dns:);
    }

    Attributes attrs;

    try {
        DirContext ictx = new InitialDirContext(env);
        attrs = ictx.getAttributes(queryInput, new String[]{queryType});
        return attrs;
    } catch ( NameNotFoundException e) {
        getLogger().debug("Resolution for domain {} failed due to {}", new Object[]{queryInput, e});
        attrs = new BasicAttributes(queryType, "NXDOMAIN",true);
        return attrs;

有没有办法将 TXT 和 A 响应注入 JNDI?

事实证明,可以使用传统的 JNDI 模拟策略(如使用 Mockito.when),但将条件钉在 getAttributes 方法中,如下面的示例代码所示:

@Before
public void setupTest() throws Exception {
    this.queryDNS =  new QueryDNS();
    this.queryDNSTestRunner = TestRunners.newTestRunner(queryDNS);

    Hashtable env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, FakeDNSInitialDirContextFactory.class.getName());

    this.queryDNS.initializeContext(env);

    final DirContext mockContext = FakeDNSInitialDirContextFactory.getLatestMockContext();

    // Capture JNDI's getAttibutes method containing the (String) queryValue and (String[]) queryType
    Mockito.when( mockContext.getAttributes(Mockito.anyString(), Mockito.any(String[].class)))
            .thenAnswer(new Answer() {
                public Object answer(InvocationOnMock invocation) throws Throwable {
                    // Craft a false DNS response
                    // Note the DNS response will not make use of any of the mocked
                    // query contents (all input is discarded and replies synthetically
                    // generated
                    return craftResponse(invocation);
                }
            });
}

// Dummy pseudo-DNS responder
private Attributes craftResponse(InvocationOnMock invocation) {
    Object[] arguments = invocation.getArguments();
    String querySubject = arguments[0].toString();
    String[] queryType = (String[]) arguments[1];

    // Create attribute
    Attributes attrs = new BasicAttributes(true);
    BasicAttribute attr;

    switch (queryType[0]) {
        case "AAAA":
            attr = new BasicAttribute("AAAA");
            attrs.put(attr);
            break;
        case "TXT":
            attr =  new BasicAttribute("TXT", "666 | 123.123.123.123/32 | Apache-NIFI | AU | nifi.org | Apache NiFi");
            attrs.put(attr);
            break;
        case "PTR":
            attr = new BasicAttribute("PTR");
            attr.add(0, "eg-apache.nifi.org.");
            attr.add(1, "apache.nifi.org.");
            attrs.put(attr);
            break;
    }
    return attrs;
}

希望这对以后的人有所帮助。