CDI @Alternative - 为每个测试用例选择替代方案

时间:2012-11-28 21:49:28

标签: java testing cdi

我想知道如何在使用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 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

CDI-Unit内置了对模拟http://jglue.org/cdi-unit/的支持 只需使用将mock指定为测试类中的producer字段。

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();
  }
}

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

您可以通过在测试中以编程方式配置CDI容器来实现。

要这样做,请在测试类的CDI容器上设置disableDiscoveryMode(),然后将测试的必要类添加到容器中(至少是测试主题 ),然后将替代类添加为替代类。

下面是一个例子。 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; }
}