2016-07-04 23 views
0

Ich mag die Abhängigkeit in Konstruktor initialisiert verspotten, in meinem Fall habe ich Kafka Produzenten verspotten will, so dass ich das Versenden von Nachrichten über kafka spotten kann, sieht mein Code wie folgt:Mocking Abhängigkeit im Konstruktor initialisiert

private Producer<String, String> producer; 

private int messageTimeOut; 
private String topicName; 

@Autowired 
public classConstructor(@Value("${bootstrap.servers}") String bootstrapServers, 
     @Value("${topic.name}") String topicName, @Value("${message.send.timeout}") int messageTimeOut) { 
    this.messageTimeOut = messageTimeOut; 
    this.topicName = topicName; 
    Properties props = new Properties(); 
    props.put("bootstrap.servers", bootstrapServers); 
    props.put("key.serializer", StringSerializer.class.getName()); 
    props.put("value.serializer", StringSerializer.class.getName()); 
    props.put("acks", "all"); 
    producer = new KafkaProducer<>(props); 
} 

Kann mir bitte jemand vorschlagen, wie dies erreicht werden kann.

+0

Ändern Sie es, so dass der KafkaProducer ein Parameter ist? – immibis

+0

Ich stimme zu, dass getan werden kann, aber ich möchte nicht die Klassenstruktur ändern. – Apollo

+0

Folgen Sie einfach dem ersten Rat von Vooks. Je nach zugrunde liegendem Framework kann es auch möglich sein, ein Framework/Annotation-Tool zu verwenden, um den Producer in die zu testende Klasse zu bringen. In der Regel möchten Sie https://www.youtube.com/playlist?list=PLD0011D00849E1B79 sehen ... gibt Ihnen eine ziemlich gute Idee, wie Sie testbaren Code schreiben. – GhostCat

Antwort

2

Es gibt keine Möglichkeit, das vom Konstruktor erstellte Objekt nachzuahmen. Im Idealfall sollten Sie beim Erstellen einer Klasse die Klasse, die Sie vortäuschen möchten, nicht instanziieren. Jedenfalls gibt es mehrere Umgehungslösungen, um dies zu erreichen.

  1. Übergeben Sie den KafkaProducer als Parameter im Konstruktor.
  2. Fügen Sie eine setKafkaProducer-Methode hinzu, die nur für Komponententests verwendet werden soll, und legen Sie das Mock-Objekt in der Klasse fest.
  3. Verwenden Reflexion des privaten Feld setzen http://www.java2s.com/Code/Java/Reflection/Setprivatefieldvalue.htm
+0

Akzeptieren dieser Antwort, weil es über sauberere Vorgehensweise spricht, d. H. Den kafkaProducer als Konstruktorargument zu übergeben. – Apollo

1

Ich denke, man PowerMock verwenden können. Es ermöglicht, ein benutzerdefiniertes Objekt bei Instanziierung zurückzugeben. Etwas wie dieses:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({TargetClass.class}) 
public class Test { 
    @Before 
    public void setUp() throws Exception { 
     PowerMockito.whenNew(TargetClass.class).withAnyArguments().thenReturn(/* instance with you target constructor arguments */); 
    } 
} 
+0

Hinweis: Jeder könnte PowerMock verwenden. Aber niemand, der nicht wirklich dringende Probleme hat (wie: keine Alternativen) sollte es tatsächlich in der Realität nutzen. Weil PowerMock in Wirklichkeit dazu neigt, viel mehr Probleme zu verursachen, als es tatsächlich löst. – GhostCat