单元测试的依赖注入与管理自己变量的类

时间:2015-06-29 22:24:29

标签: java unit-testing dependency-injection

我有一个类似这样的类(非常简化,但这是一般的想法。我实际上并没有使用原始套接字类型):

With grafico_usp
    .Name = "Metrics USP - Quantidade"
    .ChartType = xlPieExploded
    .SetSourceData Source:=rng
    .ClearToMatchStyle
    .ChartStyle = 304
    .HasTitle = True
    .HasLegend = True
    .Legend.Format.TextFrame2.TextRange.Font.Size = 13
    .Legend.Height = 200
    .Legend.Position = xlLegendPositionRight
    .ChartTitle.Text = "Estatística Número de Cursos Ofertados - USP"
    .ApplyDataLabels (xlDataLabelsShowValue)
 End With

如果我可以通过模拟套接字变量来检查通过套接字发送的内容来单元测试类的函数,那将是很有价值的。我所看到的标准方法是将构造函数修改为

class ConnectionBroker {

    private Socket socket;

    public ConnectionBroker(ConnectionDetails details) {
        socket = new Socket(details)
        //set socket paramaters
    }

    public sendOverConnection(String message) {
        //processing of message and internal queuing based on priority
        socket.send(message);
    }

    public shutdown() {
        socket.close();
    }
}

这会使单元测试变得更容易,但是我这样做有很多问题:

  • 套接字应仅由public ConnectionBroker(Socket socket) { this.socket = socket; }
  • 组成
  • ConnectionBroker类完全使用套接字的事实应该从调用类中抽象出来
  • 如果需要传入套接字,那么调用代码可能会修改ConnectionBroker类不知道的套接字上的属性

解决这个问题的正确方法是什么?我是不是想错了什么?

1 个答案:

答案 0 :(得分:1)

不确定ConnectionBroker(Socket socket)是否是标准方式,正如您所指出的那样,它有其优点和缺点。

显然,您的代码中有问题的是对new Socket(details)的调用,这会阻碍测试。

在一个几乎类似的场景中,我引入了一个新的依赖项SocketProvider,其中包含一个方法getSocket(),最终创建了套接字:

public Socket getSocket() { return new Socket();

这使得单元测试提供一个返回模拟/存根/间谍的实现或子类变得微不足道......例如,

@Mock 
private Socket mockedSocket;
@Mock 
private SocketProvider mockedProvider;

// ...
conncectionBroker.setSocketProvider(mockedProvider);

// ...

when(mockedProvider.getSocket()).return(mockedSocket); // or a stub / spy / testSocket...

它还允许为不同的环境和测试场景提供不同的实现 - IMO使其成为您建议的更好的方法(创建逻辑在单个测试的责任范围内)。