单元测试只验证几个元素

时间:2012-05-14 15:28:42

标签: java unit-testing junit mockito

有一个界面:

interface IEventListener
{
  void onEvent(List <IEvent> events);
}

有一个事件类:

class EventB
{
  private final int id;
  private final A a;
  private final String somethingElse;
...
// constructors, getters
...
}

还有一堂课要测试:

class Doer
{
 IEventListener eventListener;
 void doSomething(Aaa a)
 {
   eventListener.onEvent(Arrays.asList(new EventA(1), new EventC(2)));
...
   eventListener.onEvent(Arrays.asList(new EventB(42, a.getA(), "foo"), new EventA(3), new EventB(0, a.getA(), "bar")));
...
   eventListener.onEvent(Arrays.asList(new EventC(4)));
 }
}

Doer是我需要测试的代码,方法doSomething生成事件包,我需要测试它是否在某些特定条件下产生特定事件。

更确切地说,我希望进行单元测试,调用方法doSomething,并检查EventB是否与方法参数A一起发送“42”和a。所有其他事件都应该被忽略。

为了进行这样的测试我只提出了涉及ArgumentCaptor,for-blocks和魔术布尔标志的相当冗长的代码的解决方案......

对它进行单元测试的最佳方法是什么?也许代码设计不好?

3 个答案:

答案 0 :(得分:2)

设计是正确的,这就是你用Mockito测试它的方法:

import org.hamcrest.Matchers;
import org.mockito.Mockito;
public void firesEventsOnDoSomething() {
  Listener listener = Mockito.mock(Listener.class);
  Doer doer = new Doer(listener);
  doer.doSomething(aaa);
  Mockito.verify(listener).onEvent(
    Mockito.argThat(
      Matchers.hasItem(
        Matchers.allOf(
          Matchers.instanceOf(EventB.class),
          Matchers.hasProperty("a", Matchers.equalTo(aaa.getA())),
          // whatever you want
        )
      )
    )
  );
}

这是Mockito 1.9.0和Hamcrest-library 1.2.1。

要将JUnit 4.10与Hamcrest-library 1.2.1一起使用,您应该使用junit:junit-dep:4.10工件,并从中排除org.hamcrest:hamcrest-core

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit-dep</artifactId>
  <version>4.10</version>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest-core</artifactId>
  <version>1.2.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest-library</artifactId>
  <version>1.2.1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>1.9.0</version>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>

答案 1 :(得分:0)

如果您正在使用JUnit4,您可以尝试一个paremetrized测试。这里有一个例子http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/

如果您需要将每个参数与不同的结果进行比较,则最好将它们视为不同的测试用例。

答案 2 :(得分:0)

创建EventListener的虚拟实现:

class DummyEventListener implements EventListener {
    private int expectedId;
    DummyEventListener(int expectedId) {
       this.expectedId = expectedId;
    }
    void onEvent(List <IEvent> events) {
        for (IEvent event : events) {
            if (!(event instanceof EventB)) {
                continue;
            }
            EventB eb = (EventB)event;
            assertEquals(expectedId, eb.getId());
            // add more asserts here
        }
    }
}

或者,您可以使用一个可用的Java模型框架: EasyMock,JMock,Mockito,JMockit等。