【问题标题】:How to test object initialisation within a super constructor?如何在超级构造函数中测试对象初始化?
【发布时间】:2021-08-19 04:36:44
【问题描述】:

我有一个BasePersister,它使用 Dagger 在其构造函数中构建了一个复杂的持久性客户端:

public abstract class BasePersister {
   @Getter
   private PersistenceClient client;

   public BasePersister() {
      this.client = DaggerPersistenceClientComponent.create().getClient();
   }

   public abstract void persist(String data);

   protected void helper() {
      System.out.println("I am a helper");
   }
}

这个想法是子持久化类可以只扩展基类并与客户端一起执行其持久化逻辑。一个示例子类:

public class SpecialPersister extends BasePersister {
   public void persist(String data) {
      // do stuff with the client
      getClient().persist(data);
      // use the shared helper
      helper();
   }
}

在基类构造函数中移动客户端实例是理想的,因为在我的PersisterFactory 中,我可以简单地调用像new SpecialPersister() 这样的语句;构造函数不带任何参数,不需要 Dagger 实例化,工厂完全不知道任何客户端。

我在测试这些子类时遇到了麻烦,我怀疑这与我在基构造函数中秘密实例化客户端的设计选择有关。

更具体地说,在我的SpecialPersisterTest 类中,我不能执行Spy(SpecialPersister),因为它会调用基本构造函数,然后实例化我的复杂客户端(给我一个错误)。我需要以某种方式模拟这个超级构造函数调用,以便它实际上不会调用客户端实例化,它具有复杂的网络调用等。

理想情况下,我可以做一个简单的测试,比如检查:

def "my ideal test"() {
   given:
      specialPersister.persist(validData)
   then:
      1 * specialPersister.getClient()
   and:
      1 * specialPersister.helper()
}

【问题讨论】:

    标签: java dagger-2 spock


    【解决方案1】:

    在基类构造函数中移动客户端实例是理想的,因为在我的PersisterFactory 中,我可以简单地调用像new SpecialPersister(); 这样的语句,构造函数不带任何参数,不需要 Dagger 来实例化,工厂是完全不知道有任何客户。

    我在测试这些子类时遇到了麻烦,我怀疑这与我在基构造函数中秘密实例化客户端的设计选择有关。

    这个设计选择是个问题。如果您希望代码在不调用真实客户端的情况下可测试,您将需要能够存根您的客户端。一种选择是在实例化时传递PersistenceClient

    由于您使用的是工厂模式,因此您的工厂可以提供它,而无需担心代码中其他地方的细节。它应该知道如何创建 Persister 对象,不管它是否需要知道有关客户端的详细信息——应该鼓励在这个级别进行耦合。您可能还希望您的工厂也接受参数,以便可以测试来自工厂的 Persister。

    public abstract class BasePersister {
        private PersistenceClient client;
        public BasePersister(PersistenceClient client) {
            this.client = client;
        }
    }
    public class SpecialPersister extends BasePersister {
        public SpecialPersister(PersistenceClient client) {
            super(client);
        }
    }
    
    public class PersisterFactory {
        // pass in the client once to a PersisterFactory instance
        private PersistenceClient client;
        public PersisterFactory(PersistenceClient client) {
            this.client = client;
        }
        public SpecialPersister createSpecialPersister() {
            return new SpecialPersister(client);
        }
    }
    
    // elsewhere
    PersisterFactory persisterFactory = new PersisterFactory(DaggerPersistenceClientComponent.create().getClient());
    // ...
    BasePersister persister = persisterFactory.createSpecialPersister();
    

    【讨论】:

      猜你喜欢
      • 2011-03-09
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      • 2021-07-26
      相关资源
      最近更新 更多