Come dovrei testare un'unità di una funzione che usa setter?

2

Uso un pattern pattern di repository e ho riscontrato un ostacolo durante la scrittura di un unit test per uno dei miei metodi. Sono abbastanza nuovo nello scrivere test di unità, quindi gradirei qualsiasi aiuto!

Diciamo che ho un metodo che crea un prodotto e usa setter per impostare i dati.

public function addProduct(array $data)
{
    $new = $this->repository->make(); // returns new Product object

    $new->setTitle($data['title']);
    $new->setPrice($data['price']);
    $new->setImage($data['image']);
    $new->setStock($data['stock']);

    return $this->repository->save($new); // returns bool
}

Ora, quando scrivo i test unitari per questo metodo, cosa dovrei effettivamente provare?

  1. Dovrei semplicemente controllare il tipo di reso e lasciarlo così?
  2. Devo prendere in giro il ritorno di make() e assicurarmi che tutti i setter siano stati eseguiti?
  3. Devo prendere in giro solo repository e assicurarmi che make() e save() siano stati eseguiti?

Inizialmente, ho deciso di andare con tutte e tre le opzioni. Tuttavia, la mia preoccupazione è venuta da quando ho iniziato l'opzione 2, scrivendo dei test per garantire che tutti i setter fossero eseguiti

L'unità dovrebbe davvero preoccuparsi se tutti i setter hanno corso? Cosa succede se aggiungo altri campi? Sembra che fare questo significherebbe che il più piccolo cambiamento potrebbe comportare il fallimento del test unitario quando il metodo esegue effettivamente come eseguito.

Questo è il modo in cui ho scritto finora il mio test unitario, ma non sono sicuro di quanto sia rigoroso

public function testAddProductAddsProductWithCorrectAttributes()
{
    $newMock = Mockery::make(ProductInterface::class)
                    ->shouldReceive('setTitle')
                    ->withArgs(['Test title'])
                    ->shouldReceive('setPrice')
                    ->withArgs([10.99])
                    ->shouldReceive('setImage')
                    ->withArgs(['/foobar.jpg'])
                    ->shouldReceive('setStock')
                    ->withArgs(['In Stock']);

    $repoMock = Mockery::make(RepositoryInterface::class)
                    ->shouldReceive('make')
                    ->andReturn($newMock)
                    ->shouldReceive('save')
                    ->withArgs([$newMock])
                    ->andReturn(true);

    $service = new Service($repoMock);

    $add = $service->addProduct([
        'title' => 'Test title',
        'price' => 10.99,
        'image' => '/foobar.jpg',
        'stock' => 'In Stock'
    ]);

    $this->assertTrue($add);
}
    
posta Dan Johnson 03.05.2017 - 10:33
fonte

2 risposte

7

Quando collaudi un repository, la cosa essenziale da testare è se puoi uscire da ciò che hai inserito.

quindi ... (scusa pseudo codice)

$data = ..//whatever
addProduct(array $data)
$actual = getProduct(id)

Assert $actual == $data

Questo ovviamente fallirà se i setter non funzioneranno. Ma non prova esplicitamente ogni setter

    
risposta data 03.05.2017 - 11:04
fonte
3

Lo scopo di addProduct() è garantire che (a) esista un nuovo prodotto e (b) contenga i valori di campo specificati dagli argomenti. Pertanto, sì, il test unitario dovrebbe assolutamente interessare se tutti i setter hanno funzionato e se questi sono tutti gli attributi dell'oggetto.

Se non gli interessa, allora molto probabilmente introdurrai dei difetti quando cambierà la serie di attributi. Così com'è, la suite di test ti avvisa automaticamente subito dopo aver introdotto un nuovo attributo. Credimi, le notifiche fastidiose sono molto migliori dei difetti non notati.

    
risposta data 03.05.2017 - 10:41
fonte

Leggi altre domande sui tag