EJB 无接口视图测试(arquiillain & mockito)

Alb*_*Bos 4 java ejb mockito ejb-3.1 jboss-arquillian

我正在开发 Java EE 7(在 Wildfly 9.0.2 上)应用程序,偶然发现了一篇文章http://www.oracle.com/technetwork/articles/java/intondemand-1444614.html。主要是关于:

过早的可扩展性是一些邪恶的根源

这在我遇到的某些情况下是有道理的。我已将一些类更改为无界面视图。实现本身不是问题,但是测试是。

例如我有这两个类。

@Stateless
public class SomeBean {
     public String getText()
     {
         return "Test text";
     }
}
Run Code Online (Sandbox Code Playgroud)

@Stateless
public class SomeOtherBean {
    @Inject
    private SomeBean someBean;

    public String getText()
    {
        return someBean.getText();
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望以某种方式最好用模拟对象覆盖 someBean 属性。不改变SomeBeanSomeOtherBean类。我尝试了一些示例,但它们不起作用,例如:https : //github.com/arquillian/arquillian-showcase/tree/master/extensions/autodiscover/src/test/java/org/jboss/arquillian/showcase /扩展/自动发现

有没有人遇到过这个问题并有解决方案?

Alb*_*Bos 5

我最终使用了 2 个解决方案。

解决方案 1:使用 mockito 进行内部或较小的测试

对于测试特定的类 Mockito 非常有用,因为它支持依赖注入。

@RunWith(MockitoJUnitRunner.class)
public class SomeOtherBeanTest {
    @Mock
    private SomeBean someBean;

    @InjectMocks
    private SomeOtherBean someOhterBean;

    @Before
    public void setUp() {
        Mockito.when(someBean.getText()).thenReturn("Overwritten!");
    }

    @Test
    public void testGetText() throws Exception {
        assertEquals("Overwritten!", someOhterBean.getText());
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案 2:使用 @Produces 和 @Alternatives 来模拟外部服务(例如模拟 OAuth2 服务器)或更大的测试(例如集成测试)

首先,我创建一个新@Alternative注释:

@Alternative
@Stereotype
@Retention(RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface CDIMock {}
Run Code Online (Sandbox Code Playgroud)

然后将此作为构造型添加到 arquillianbeans.xml部署中:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
    <alternatives>
        <stereotype>com.project.CDIMock</stereotype>
    </alternatives>
</beans>
Run Code Online (Sandbox Code Playgroud)

之后@Producer在单独的类中创建一个新方法:

public class SomeBeanMockProducer {
    @Produces @CDIMock
    public static SomeBean produce() {
        SomeBean someBean = Mockito.mock(SomeBean.class);
        Mockito.when(someBean.getText()).thenReturn("mocked");

        return someBean;
    }  
}
Run Code Online (Sandbox Code Playgroud)

SomeBeanMockProducer类添加到 arquillian 部署中,您应该让它工作。

此解决方案的替代方案是使用@Specializes和扩展 SomeBean 实现。在我看来,这并没有像@Alternative+ Mocking 解决方案那样给我足够的控制权(@CDIMock在我的例子中)。

例如,假设我SomeBean有调用远程服务器的方法。如果我为此添加一个方法并@override@Specializes类中忘记了this,它将进行真正的远程调用,而 Mocking 则不会出现这种情况。