如何覆盖特定的Seam组件?

时间:2010-07-21 20:35:16

标签: java ant mocking seam

我使用以下签名嘲笑了一些接缝组件:

@Name("myService")
@Install(debug = true, precedence = Install.MOCK)
public class MyServiceMock implements MyService

我通过更改components.xml

中的这一行来启用我的模拟
<core:init transaction-management-enabled="false"  />

到此:

<core:init transaction-management-enabled="false" debug="true" />

当我想模拟所有类时,这很好。我刚用我的ant脚本用调试版替换了我的普通components.xml。

有没有办法有条件地嘲笑一个或多个组件?一个理想的解决方案允许我指定在外部文件中模拟哪些组件,例如components.properties或其他属性文件。


我的解决方案


以下是我根据germanescobar's回答确定的内容。

我更改了我的模拟组件签名以匹配:

@Name("myService")
@Install(false)
public class MyServiceMock implements MyService

然后我为要模拟的components.xml添加了一行代码,如下所示:

<component name="myService" installed="false" precedence="40"
               class="com.foo.bar.baz.service.MyServiceMock" />

要启用模拟,我设置installed=true

2 个答案:

答案 0 :(得分:1)

您可以依靠 org.jboss.seam.postInitialization 事件

  

当Seam初始化并启动所有组件时调用

or org.jboss.seam.postAuthenticate。&lt; username&gt;

  

在用户通过身份验证后调用,例如devMode

因此,创建您的ConformedEventComponent并定义其@Observer事件

@Name("conditionallyEventComponent")
@Scope(ScopeType.APPLICATION)
public class ConditionallyEvent {

    @Observer("org.jboss.seam.postInitialization", create=true)
    /*
     * or @Observer("org.jboss.seam.postAuthenticate.devMode", create=true)
     */
    public void postInitialization() {
        /**
          * An ideal solution would allow me to specify which components to mock out in an external file
          */

        /**
          * Here i am overriding ApplicationScoped components
          *
          * Maybe you want something like
          * applicationContext.properties
          * sessionContext.properties
          */

        Context context = Contexts.getApplicationContext();

        ResourceBundle resourceBundle = ResourceBundle.getBundle("applicationContext");
        Enumeration<String> keyEnumeration = resourceBundle.getKeys();
        while(keyEnumeration.hasMoreElements()) {
            String key = keyEnumeration.nextElement();
            /**
              * Keep in mind newInstance method needs no-arg constructor
              */
            context.set(key, Class.forName(resourceBundle.getString(key)).newInstance());
        }

    }

}

通过提供create属性,您还可以指定在事件被引发时是否存在创建观察者组件

您还可以按如下方式提供系统属性

-Dprofile=development

查看Application Server文档如何设置系统属性。在postInitialization(或postAuthenticate)事件

@Observer("org.jboss.seam.postInitialization", create=true)
public void postInitialization() {
    Properties properties = System.getProperties();

    String profile = properties.getProperty("profile");
    if(profile != null && profile.equals("development")) {
        // do as shown above
    }
}

答案 1 :(得分:1)

当我只想覆盖某些组件时,我通常会使用components.xml文件。因此,例如,如果我有一个MyService接口,其默认实现如下:

@Name("myService")
public class DefaultMyService implements MyService 

我想只覆盖那个特定的类,我将以下内容添加到components.xml:

<component name="myService" class="org.gescobar.MockMyService" precedence="30" />

请看一下优先顺序。默认情况下,每个组件的优先级都为20,因此30将覆盖该组件。您可以将components.xml视为外部文件(或Spring用户的application-context.xml),您可以在其中覆盖所需的任何组件。