CQRS e event sourcing

CQRS e Event Sourcing: il nostro primo progetto andato in produzione – Parte 3 Testing

Pubblicato il da

Riccardo

Riccardo

Partner

In Flowing crediamo molto nella qualità del codice e di conseguenza nei test automatici. In Soisy non abbiamo fatto eccezione e come vedremo a breve, grazie alle componenti di Broadway, fare test unitari sulla nostra logica di business è veramente facile.

Anche in questo caso andremo ad implementare due tipologie di test unitari rispettivamente per la scrittura e per la lettura.

Come testare un comando (e quindi controllare che il giusto evento verrà salvato)

Negli articoli precedenti abbiamo visto come possiamo approvare un prestito ovvero:  “dato che un prestito è stato richiesto, quando viene inviato il comando ApproveLoan allora dovrà essere salvato un evento LoanApproved”.

Con broadway possiamo implementare il test proprio come descritto sopra:

   /**
    * @test
    */
   public function it_can_approve_a_loan()
   {
      $loanId = new LoanId(‘000’);
      $requestedAt = new \DateTime(‘2016-07-30’);       
      $approvedAt = new \DateTime(‘2016-07-30’);
      $amount = 500;
      $instalmentNumber = 12;
      $status = ‘OK’;

      $this->scenario
          ->withAggregateId($loanId)
          ->given([
              new LoanWasRequested($loanId, $amount, $instalmentNumber, $requestedAt)
          ])
          ->when(new ApproveLoan($event->getLoanId(), $approvedAt))
          ->then([
              new LoanApproved(
                  $loanId,
                  $status,
                  $approvedAt
              )
          ]);
   }

Broadway implementa la classe Scenario che espone un’interfaccia fluente con in metodi given, when, then e internamente utilizza un InMemory repository come mock dell’event store. Cosi facendo i test sono isolati dal database e molto veloci.

Given prende come parametro un array di eventi che verranno applicati all’aggregato Loan il quale verrà quindi ricostruito e portato in un determinato stato, che per noi è quello che assume dopo che l’utente ha richiesto un prestito.

When prende un comando che verrà inviato all’aggregato Loan. In sostanza verrà chiamato il metodo Loan::approve il quale applicherà l’evento LoanApproved con lo stato desiderato ovvero con $status == ‘OK’ dato che stiamo testando un approvazione.

Then è il metodo che effettua l’asserzione di uguaglianza tra il vero evento applicato (actual) e l’evento LoanApproved che gli stiamo passando come parametro (expected).

Stiamo quindi testando che dato un comando verrà salvato l’evento che ci aspettiamo, con lo stato voluto.

Come testare la proiezione (e quindi che il giusto read model sia salvato)

Applichiamo gli stessi concetti per il testing del read model ovvero: “dato che è stato richiesto un prestito, quando il prestito verrà approvato allora il read model verrà correttamente aggiornato e salvato”.

  /**
   * @test
   */
   public function it_projects_approved_at_when_approved()
   {
      $loanId = new LoanId(‘000’);
      $requestedAt = new \DateTime(‘2016-07-30’);       
      $approvedAt = new \DateTime(‘2016-07-30’);
      $amount = 500;
      $instalmentNumber = 12;
      $status = ‘OK’;

      $expecetdLoan = new Loan($loanId, $amount, $instalmentNumber, $requestedAt); //read model
      $expecetdLoan>setApprovedAt($approvedAt);
      $expecetdLoan>setStatus($status);

       $this->scenario
           ->given([new LoanWasRequested($loanId, $amount, $instalmentNumber, $requestedAt)])
           ->when(new LoanApproved(
                   $loanId,
                   $status,
                   $approvedAt
                 ))
           ->then([
               $expecetdLoan
           ]);
   }

Come potete vedere il gioco è sempre lo stesso solo che questa volta, la when prende un evento dato che il read model verrà modificato solo dopo che l’evento è accaduto. Il then si assicura che il read model generato dal codice di produzione sia quello che ci aspettiamo ovvero $expecetdLoan.

Broadway mette a disposizione nel repository git degli esempi di utilizzo.
Nel prossimo post vedremo come implementare un’api in cqrs + event sourcing. I post precedenti su ‘CQRS e Event Sourcing: il nostro primo progetto andato in produzione’ li trovi qui: Write side, Read side.