Testowanie CRUDa

Odpowiedz Nowy wątek
2019-07-17 08:48

Rejestracja: 1 rok temu

Ostatnio: 6 godzin temu

0

Mam taki kod:

var review = await _db.Reviews.FindAsync(request.ProductId, request.CustomerId);

if (review == null)
    return new Result(ErrorType.NotValid, "Recenzja nie istnieje.");

_db.Reviews.Remove(review);
await _db.SaveChangesAsync(cancellationToken);

return Result.SuccessfulResult;

Czy warto go testować? Na pierwszy rzut oka widać, że będzie działał. Testy jednostkowe do niego kosztują 70 linijek, podczas gdy cała klasa z tym kodem ma ich 35. Czy testy nie powinno się pisać tylko dla jakiejś skomplikowanej logiki? W mojej aplikacji mam praktycznie same CRUDy. Co ja mam w niej testować?

Pozostało 580 znaków

2019-07-17 09:39

Rejestracja: 5 lat temu

Ostatnio: 1 godzina temu

Lokalizacja: Nowa Ruda

2

Też mam same CRUDy ale dzięki testom czasami wyłapuje jakieś brzegowe przypadki złego działania.

Pozostało 580 znaków

2019-07-17 09:48
Moderator

Rejestracja: 12 lat temu

Ostatnio: 53 minuty temu

Lokalizacja: Wrocław

1

Testy jednostkowe do niego kosztują 70 linijek

Testy jednostkowe na zasadzie zrób mocki do wszystkiego i niech się dzieje wola nieba? :-P


edytowany 1x, ostatnio: Patryk27, 2019-07-17 09:48

Pozostało 580 znaków

2019-07-17 09:51

Rejestracja: 5 lat temu

Ostatnio: 1 godzina temu

Lokalizacja: Nowa Ruda

0
Patryk27 napisał(a):

Testy jednostkowe do niego kosztują 70 linijek

Testy jednostkowe na zasadzie zrób mocki do wszystkiego i niech się dzieje wola nieba? :-P

Jeśli to jest EF Core to pewnie EFInMemory i zapełnia danymi i testuje poprawne zachowanie

Pozostało 580 znaków

2019-07-17 09:52

Rejestracja: 1 rok temu

Ostatnio: 6 godzin temu

0

@Patryk27: Wyglądają tak:

using System;
using System.Threading;
using System.Threading.Tasks;
using MyStore.Application.Interfaces.Security;
using MyStore.Application.Products.CommandHandlers;
using MyStore.Application.Products.Commands;
using MyStore.Common.Types.Results;
using MyStore.Database;
using MyStore.Model;
using MyStore.Tests.Infrastructure;
using Shouldly;
using Xunit;

namespace MyStore.Tests.Products.CommandHandlers
{
    [Collection(nameof(ApplicationCollection))]
    public class DeleteReviewHandlerTests : IDisposable
    {
        private readonly ApplicationDbContext _db;
        private readonly IAuthContext _auth;

        public DeleteReviewHandlerTests(ApplicationFixture fixture)
        {
            _db = fixture.Db;
            _auth = fixture.Auth;
        }

        [Fact]
        public async Task Should_Not_Delete_Review_When_Review_Does_Not_Exist()
        {
            var handler = new DeleteReviewHandler(_db, _auth);

            var command = new DeleteReview(100, _auth.GetCurrentCustomerId());

            var result = await handler.Handle(command, CancellationToken.None);

            result.IsSuccessful.ShouldBe(false);
            result.Error.Type.ShouldBe(ErrorType.NotValid);
        }

        [Fact]
        public async Task Should_Delete_Review()
        {
            var review = new Review
            {
                ProductId = 1,
                AuthorId = _auth.GetCurrentCustomerId(),
                Stars = 5,
                Content = "Test Content"
            };

            _db.Reviews.Add(review);
            _db.SaveChanges();

            var handler = new DeleteReviewHandler(_db, _auth);

            var command = new DeleteReview(review.ProductId, review.AuthorId);

            var result = await handler.Handle(command, CancellationToken.None);

            result.IsSuccessful.ShouldBe(true);
        }

        public void Dispose()
        {
            _db.Reviews.RemoveRange();
            _db.SaveChanges();
        }
    }
}

Pozostało 580 znaków

2019-07-17 09:58

Rejestracja: 5 lat temu

Ostatnio: 1 godzina temu

Lokalizacja: Nowa Ruda

1

Ja bym sprawdzał czy na pewno obiekt został usunięty z bazy. Bo jak pominiesz w kodzie savechangs to test też przejdzie :)

Pozostało 580 znaków

2019-07-17 09:59

Rejestracja: 1 rok temu

Ostatnio: 6 godzin temu

0

@szydlak: Wiem, miałem to dziś dopisać. ;) W ogóle testy i kod są trochę rozsynchronizowane ze sobą, więc nie analizujcie, czy wszystko ma sens, chodzi jedynie o ideę. ;)

Pozostało 580 znaków

2019-07-17 13:46

Rejestracja: 4 lata temu

Ostatnio: 3 tygodnie temu

Lokalizacja: Chorzów

1

to bardziej integracyjne niż jednostkowe :P chyba, że zrobisz abstakcję na usuwanie, pobieranie i dodawanie ;) :D

Pozostało 580 znaków

2019-08-23 20:59

Rejestracja: 1 rok temu

Ostatnio: 6 godzin temu

0

Czytam sobie ostatnio o testach integracyjnych i zastanawiam się, czy nie lepiej byłoby ich użyć w zamian "jednostkowych" (takich jak wyżej). Żeby było jasne: mam na myśli coś takiego: https://docs.microsoft.com/pl[...]ion-tests?view=aspnetcore-2.2
Aby zwiększyć wydajność mógłbym podpiąć SQLite'a in-memory i skorzystać z collection fixtures. Miałbym np taki kod:

[Fact]
public async Task Should_Register_User()
{
    var command = new Register("User1", "[email protected]", "Secret123");

    var response = await _client.PostAsync("/api/auth/register", GetPayload(command));

    response.EnsureSuccessStatusCode();
}

Różnica w wydajności nie powinna być duża w takim przypadku. @Aventus pisał kiedyś, że jego zdaniem testy jednostkowe należy ograniczyć do minimum i stosować je tylko tam, gdzie faktycznie przynoszą jakieś korzyści. Czy testy integracyjne wyglądają wówczas tak, że testuje się każdą ścieżkę egzekucji żadania osobno? Testowanie jedynie happy path to chyba za mało.

edytowany 1x, ostatnio: nobody01, 2019-08-23 21:03

Pozostało 580 znaków

2019-08-23 22:29

Rejestracja: 3 lata temu

Ostatnio: 47 minut temu

Lokalizacja: UK

0

Gwoli ścisłości, ja opowiadałem się za czymś pośrednim między testem jednostkowym a integracyjnym. W takim przypadku test uderza w endpoint (za pomocą hosta w pamięci opisanego w Twoim linku), natomiast wszelkie inne zależności których w konkretnym teście nie chcę sprawdzać podmieniam- czy to za pomocą biblioteki mockującej czy "manualnie" dostarczając testową implementację intefejsu.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.

Pozostało 580 znaków

2019-08-23 22:35

Rejestracja: 1 rok temu

Ostatnio: 6 godzin temu

0

@Aventus: Moglbys podac jakis przyklad? Nie moge sobie tego wyobrazic :(

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0