2017-05-02 2 views
2

Ich habe eine Frage in Bezug auf die Frage Time dependent unit testsWie abstrahieren java.time.Clock zu Testzwecken im Frühjahr

Lasst uns sagen, dass ich Frühling Anwendung zu erstellen, die Service-Schnittstelle und deren Umsetzung enthält

Wenn ich will die uhr im test ändern, ich müsste produktionscode "verschmutzen" und mit zb interface verbinden setClock Verfahren wie folgt:

public interface MyService { 
    void heavyBusinessLogic(); 
    void setClock(Clock clock); 
} 

@Service 
public class MyServiceImpl implements MyService { 

    private Clock clock = Clock.systemDefaultZone(); 

    @Override 
    public void heavyBusinessLogic() { 
     if (LocalDate.now(clock)...) { 
      ... 
     } 
    } 

    @Override 
    public void setClock(Clock clock) { 
     this.clock = clock; 
    } 
} 

Im Test rufe ich kann, z.B .:

service.setClock(Clock.fixed(Instant.parse("2017-02-14T01:22:00Z"), ZoneOffset.UTC)); 

Wie kann ich abstrahieren solche Querschnittsthema im Frühjahr?

ich mit java.time.Clock halten wollen (ich will nicht Joda verwenden)

+0

Warum nicht stattdessen Konstruktor-Injektion verwenden? Dann gibt es keine 'setClock()' Methode in der Schnittstelle –

+0

java.time.Clock ist keine Bean –

+2

... was kein Problem ist, da Sie eine Clock Bean in Ihrer produktiven Konfiguration und eine gemockte in Ihrer definieren können Testkonfiguration ... –

Antwort

5

Persönlich würde ich einfach die Uhr im Konstruktor hinzufügen ...

public MyServiceImpl(Clock clock) { 
    this.clock = clock; 
} 

. ..und vielleicht einen schönen Standardkonstruktors hinzufügen ...

public MyServiceImpl() { 
    this(Clock.systemDefaultZone()); 
} 

diese Weise können Sie das Standard-Ding über Feder bekommen können und eine benutzerdefinierte Uhr Version manuell erstellen, zum Beispiel in Ihren Tests.

Natürlich könnten Sie auch das Standard-Konstruktor verzichten und einfach eine Clock Bohne in Ihrer produktiven Konfiguration hinzuzufügen, zum Beispiel wie folgt aus ...

@Bean 
public Clock clock() { 
return Clock.systemDefaultZone(); 
} 

... die Sie verspotteten verwenden können Clock als eine Bohne in Ihrer Testkonfiguration, die Spring automatisch zu @Autowire es über Konstruktoreinspritzung erlaubt.

+0

Ich bin gerade auf ein anderes Problem gestoßen. Ich würde gerne die Uhr für zeitkritische Vergleiche in der Entität selbst verwenden und ich denke, das Einspritzen von Clock Bean ist keine gute Idee. Was schlagen Sie vor? –

+0

Warum denken Sie, dass es keine gute Idee ist? Ich sehe nicht das Problem damit ... –

+0

Es erfordert entweder Aspectj Laden Zeit Weben oder Hibernate LoadEventListener. Ich dachte, es gibt einen standardisierten Weg, es zu tun :) –