3

我想知道在使用 CDI 时如何指定在测试期间应该使用哪个模拟实现。

我知道我可以用@Alternative 标记一个模拟实现,但是我需要在beans.xml 中定义它。我想要多个模拟(用于多个对象)。假设我有一个 OrderService 和一个 EmailService。我正在编写一些不希望 EmailService 发送电子邮件的验收测试。然后是系统测试的另一组测试 - 我确实想发送电子邮件,但不应该创建真正的订单。

理想的解决方案是为每个测试方法调用指定 Alternatives,如下所示:

@BeforeMethod
public void before(){
  // in this test suite we're using mock email service
  addAlternative(MockEmailService.class);
}
@Test
public void testMyStuff(){
  issueAnOrder(); // and verify that it worked. no emails sent!
}

是否可以?

4

4 回答 4

2

CDI-Unit 内置了对模拟http://jglue.org/cdi-unit/的支持, 只需在测试类中将模拟指定为生产者字段即可。

class Starship {

  @Inject
  Engine engine; //This will be mocked

  void start() {
    engine.start();
  }
}


@RunWith(CdiRunner.class)
class TestStarship {

  @Inject
  Starship starship;

  @Produces
  @Mock // Mockito will create a mock for us.
  Engine engine;

  @Test
  public void testStart() {
    starship.start();

    // Verify that the mocks start method is called at least once.
    Mockito.verify(engine, Mockito.atLeastOnce()).start();
  }
}
于 2013-03-06T10:42:50.293 回答
1

我认为您需要 @Alternative/@Specialisation 和 Arquillian 的组合。Arquillian为集成测试提供了新的可能性,并允许您通过更改“beans.xml”为每个测试指定不同的替代方案。具体细节请参考这个问题。

于 2012-11-29T12:53:44.647 回答
0

Roland 可能是最好的可接受的答案,另一种可能的方法是创建一个可移植的扩展程序,它将读取您在测试或环境中设置的一些属性以及 ProcessAnnotatedType.veto() 您不想要的版本。

Arquillian 的另一个选择是不捆绑所有替代方案,而是有多个部署可供选择。

于 2012-11-29T15:05:06.633 回答
0

您可以通过在测试中以编程方式配置 CDI 容器来做到这一点。

为此,disableDiscoveryMode()请在您的测试类中设置您的 CDI 容器,将测试所需的类添加到容器中(至少是您的测试主题替代类),并将替代类添加为替代类。

下面举个例子。Greeter 是我的测试对象, Greeting 是默认 bean, GreetingAlt 是替代品。

测试类:

public class GreeterTest {

    private Greeter greeter;

    @Before
    public void setUp() {
        try (WeldContainer container = new Weld().disableDiscovery()
                .addBeanClass(Greeter.class)
                .addBeanClass(Greeting.class)
                .addBeanClass(GreetingAlt.class)
                .addAlternative(GreetingAlt.class).initialize()) {
            greeter = container.select(Greeter.class).get();
        }
    }

    @Test
    public void hiShouldContainMock() {
        assertThat(greeter.hi(), containsString("Mock"));
    }
}

主要课程:

public class Greeter {
    @Inject IGreeting iGreeting;
    public String hi() { return iGreeting.greet("John"); }
}
@Default
public class Greeting implements IGreeting {
    @Override public String greet(String name) { return "Hello " + name; }
}
@Alternative
public class AltGreeting implements IGreeting {
    @Override public String greet(String name) { return "Mock " + name; }
}
于 2020-01-08T14:42:08.317 回答