1

我有一段代码大致相当于以下内容。


public class ConcreteThread extends OtherThread {
  private DAOfirst firstDAO;
  private DAOsecond secondDAO;
  private TransformService transformService;
  private NetworkService networkService;

  public ConcreteThread(DAOfirst first, DAOsecond second, TransformService service1, 
       NetworkService service2) {
    firstDAO = first;
    secondDAO = second;
    transformService = service1;
    networkService = service2;
  }

  public Future go() {
    Results r1 = firstDAO.getResults();
    MyCallable c1 = new MyCallable(r1);
    return super.getThreadPool().submit(c1);
  }

  private class MyCallable implements Callable {   
    private Results result; 
    private Long count;
    private MyCallable(Results r) {
      this.result = r;
      this.count = new Long(0);
    }

    public Long call() {
      Singleton transactions = Singleton.getInstance();
      try {
        transactions.begin();
        while(result != null) {
          Transformed t = transformService.transform(r1);
          networkService.sendSomewhere(t);
          count = count += result.size();
          secondDao.persist(result);
          result = firstDao.getNext(result);
        }
      }
      catch (Exception e) {
        e.printStackTrace();
      }
      finally {
         transactions.end(); 
      }
    }
  }
 

这些类(内部或外部)都没有单元测试,事实证明内部类 ,MyCallable有一个错误。在我上面给你的代码的简化版本中,这个错误不存在。

因此,假设您决定修复错误,并为MyCallable. 我的问题是这个;您将如何为MyCallable内部类编写单元测试?

我自己的解决方案是首先重构MyCallableConcreteThread. MyCallable在它自己的文件中创建了一个公共类,ConcreteThread现在将 DAO、Services 和 Singleton 作为构造函数参数传递给MyCallable,而不是依赖于内部类对它的私有变量的访问。

然后,我在单元测试中大量使用 EasyMock 来模拟这些依赖项并验证它们是否以我预期的方式被调用。

所有这一切的结果是代码MyCallable比以前大了一些。由于它不再可以访问 中的私有变量ConcreteThreadConcreteThread因此必须将它们作为参数传入构造函数中,并将MyCallable它们设置为私有变量。

你认为这是错误的做法吗?也许通过执行这种重构,我破坏了封装并在代码库中添加了不必要的样板?你会在测试中使用反射吗?

4

2 回答 2

3

所有这一切的结果是 MyCallable 的代码比以前要大一些。由于它不再可以访问 ConcreteThread 中的私有变量,因此 ConcreteThread 必须将它们作为参数传入构造函数中,而 MyCallable 将它们设置为私有变量。

这是一个很好的结果,MyCallable 不再依赖于 ConcreteThread 的变化。

我认为问题和答案是相当主观的,但我认为您在重构中遵循了SOLID原则(这是一件好事)。

如果可以的话,让 MyCallable 包受到保护,而不是公开:)

于 2011-02-18T11:33:00.457 回答
1

在我看来,内部类是外部类的实现细节。

所以我提出这个问题,你能通过为 ConcreteThread.Go() 编写一个失败的单元测试来证明这个错误吗?对内部类进行更改后应该有什么不同 - 外部可见的更改是什么?一旦你弄清楚了 - 你就会上路。

于 2011-02-18T12:07:26.190 回答