【问题标题】:Mockito: check if internet connection existsMockito:检查互联网连接是否存在
【发布时间】:2016-12-05 21:26:24
【问题描述】:

我正在对服务类 A 进行单元测试,该服务类从 B 类加载数据。它们的设置如下:

public class A {

    private B b;

    public A (B b)
        this.b = b;
    }

    public String getInfo() throws IOException {
        return b.getData()
    }

}

public class B {

    public String getData() throws IOException {
        //gets data from the internet
        //throws IOException if it can't connect to the internet
    }   

}

所以基本上我决定在我的 setUp 方法中像这样模拟它

private static A a;

@BeforeClass
public static void setUp() {
    B b = mock(B.class);
    when(b.getData()).then(invocation -> {
        try {
        final URL url = new URL("http://www.google.com");
        final URLConnection conn = url.openConnection();
      } catch (IOException ex) {
        throw new IOException(ex);
      }
      //some other operations follow after this, but they all work
      return "...";
    });
    this.a = new A(b);
}

测试调用 A 的 getInfo() 方法。每当我断开我的路由器(然后运行测试)时,它应该抛出一个异常(无论如何,当我在模拟之外尝试它时会抛出异常)。但是,在模拟时,它永远不会进入异常块 - 它只是通过 openConnection() 调用,就像没有问题一样。为什么会这样?

【问题讨论】:

  • docs.oracle.com/javase/7/docs/api/java/net/… 似乎表明它实际上并没有打开连接,只是连接了一个。
  • 单元测试不应依赖于您的互联网连接状态。 Mockito 的重点是允许您删除此类依赖项。
  • 那么在没有连接时测试一个类是否真的表现得像它应该的那样没有意义吗?我只是想知道这是否可能。如果我使用带有预制响应的存根,我可以做同样的事情,但使用 Mockito 根本不可能吗?
  • 如果您正在测试A,您需要测试A 的唯一事情是它是否正确处理B,如果它提供了结果,并且它是否抛出异常.如果你想测试B 处理无连接,那么你不应该嘲笑它。
  • 如果你想测试 B.getData() 是否抛出异常,或者没有连接的特定异常,那么你需要在 B 的测试中模拟你的连接,并检查当您的模拟连接断开时会引发异常。如何“模拟你的连接”将取决于 B.getData() 的作用。无论如何,B.getData() 是否抛出,或者它抛出什么,在什么情况下,都不是 A 关心的,所以它不应该在 A 的单元测试中。

标签: java unit-testing exception mockito


【解决方案1】:

嗯,是的,但是当没有连接时,B 应该抛出异常。所以基本上没有办法用 Mockito 做到这一点?

有可能:

@Rule
public MockitoRule rule = MockitoJUnit.rule();
@Rule
public ExpectedException exception = ExpectedException.none();

@Mock B b;

@Test
public void getInfo_ExceptionThrownByB_ExceptionFallsThrough(){
   // prepare
   doThrow(new IOException("unitTest"))when(b).getData();
   A a = new A(b);
   // assert (before act because exceptions are special)
   exception.expect(IOException.class);
   exception.expectMessage("unitTest");
   // act 
   a.getInfo();
}

我认为重点是:(你自己)清楚你测试的内容。您测试的任何内容(可以是,但通常不超过一个类)不应被嘲笑。您在测试下编写的任何与 交互的代码都应该 被模拟(除非这种依赖关系像 DTO 那样容易破坏,或者不太可能像 JRE 类那样改变,例如:集合)。

【讨论】:

    猜你喜欢
    • 2010-11-26
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2017-06-07
    相关资源
    最近更新 更多