【问题标题】:Creating Mock JMX Servers and Beans in Groovy在 Groovy 中创建 Mock JMX 服务器和 Bean
【发布时间】:2025-12-28 02:50:11
【问题描述】:

我们正在监视具有大量自定义 MBean 和属性的自定义应用程序。长期以来,我们一直在实验室中对服务器进行功能测试,但现在我们想要创建不依赖实际远程连接的适当单元测试。

就我自己而言,我根本无法弄清楚如何使用 Groovy JMX 构建器来启动本地 MBeanServer,并使用属性和操作列表公开本地 mbean。

有人愿意提供这种模型的示例吗?我为 jmxbuilder 找到的现有示例无法让我到达那里,但看起来应该是可能的。

【问题讨论】:

    标签: unit-testing groovy jmx


    【解决方案1】:

    Spock 测试的简单示例

    • 将 groovy bean 导出到 JMX 中
    • 导入和使用这个 bean

    代码:

    class JMXSpec extends Specification {
    
        class MyBean {
            def property
        }
    
        def "launch and test a mbean"() {
            given: "a mbean exported"
    
                def jmx = new JmxBuilder()
                jmx.export {
                    // Export every properties/methods of 'MyBean' 
                    // under 'Groovy.Test:name=MyBean'
                    bean(
                        target:new MyBean(property:"test"),
                        name:"Groovy.Test:name=MyBean"
                    )
    
                }
    
            and: "a mbean imported from the local server"
                def mbean = new GroovyMBean(ManagementFactory.getPlatformMBeanServer(), 
                    "Groovy.Test:name=MyBean")
            expect:
                "test" == mbean.Property
        }
    }
    

    【讨论】:

    • 哇,这可能正是我需要的,谢谢!在这里学到了很多。当您执行 bean 的 jmx.export 时,您“定位”任何 pojo 或 pogo 的实例,并给出名称,非常酷!我可以获取“MBeanServerConnection”对象然后使用 QueryNames 吗?另外,我注意到您在 mbean.Property 上使用了 Capital P,它可以工作,而 .property 不起作用,那里发生了什么?我以前从未在 mbean 属性名称中使用正确的大小写。
    • 我不知道首都。这是注册mbean属性的方式,但我真的不知道为什么。您可以使用带有 MBeanServerConnection 的 GroovyMBean,但它不支持查询:您必须执行查询,然后使用找到的名称创建 GroovyMBean
    【解决方案2】:

    这是我使用的(Java 中的示例,而不是 Groovy....)

    /**
     * Creates a new visible MBeanServer
     * @param name The MBeanServer's default domain name
     * @param xregPlatform true to register all known PlatformManagedObject in the created MBeanServer, false otherwise
     * @return the new MBeanServer
     */
    public static synchronized MBeanServer createMBeanServer(final String name, final boolean xregPlatform) {
        MBeanServer mbs = getLocalMBeanServer(name);
        if(mbs==null) {
            mbs = MBeanServerFactory.createMBeanServer(name);
        }
        if(xregPlatform) {
            registerPlatformManagedObjects(mbs);
        }
        return mbs;
    }
    

    有关其他方法的详细信息,请参阅我的JMXHelper

    【讨论】:

    • 感谢您的这篇文章。它在概念上肯定有帮助。您是否创建任何 bean 和属性?
    • 我仍然希望 Groovy 开发人员有一天能够在 Groovy 中提供完整的解决方案。我认为这是一个很常见的用例。
    【解决方案3】:

    另外,为了后代,这里是一个稍微修改的示例,模仿常见的“queryNames”方法...

    import groovy.jmx.builder.JmxBuilder
    import spock.lang.Specification
    import javax.management.ObjectName
    import java.lang.management.ManagementFactory
    
    
    class SandboxJmxBuilderSpec extends Specification {
        class MyBean {
            def property
        }
    
        def "launch and test a mbean"() {
            given: "a mbean exported"
    
            def jmx = new JmxBuilder()
            jmx.export {
                // Export every properties/methods of 'MyBean'
                // under 'Groovy.Test:name=MyBean'
                bean(
                        target:new MyBean(property:"test"),
                        name:"Groovy.Test:name=MyBean"
                )
    
            }
    
            and: "a mbean imported from the local server"
            def mbs = ManagementFactory.getPlatformMBeanServer()
            def queryString = "Groovy.Test:name=MyBean"
            def discovery = mbs.queryNames(new ObjectName(queryString), null)
    
            expect:
            "test" == new GroovyMBean(mbs, discovery[0]).Property
        }
    }
    

    【讨论】: