2012-09-21 20 views
59

Jak wyłudzić bazę danych w mojej aplikacji node.js, która w tym przypadku używa mongodb jako zaplecza dla interfejsu API REST bloga?Prześmiewanie bazy danych w pliku node.js?

Oczywiście mogę ustawić bazę danych na konkretną bazę danych testing, ale nadal będę zapisywać dane i nie testować tylko mojego kodu, ale także bazy danych, więc w rzeczywistości nie wykonuję testów jednostkowych, ale testowania integracji.
Co więc należy zrobić? Tworzenie wrapperów baz danych jako środkowej warstwy między aplikacją a bazą danych i zastąpienie DAL podczas testowania?

// app.js 
var express = require('express'); 
    app = express(), 
    mongo = require('mongoskin'), 
    db = mongo.db('localhost:27017/test?auto_reconnect'); 

app.get('/posts/:slug', function(req, res){ 
    db.collection('posts').findOne({slug: req.params.slug}, function (err, post) { 
     res.send(JSON.stringify(post), 200); 
    }); 
}); 

app.listen(3000); 

// test.js 
r = require('requestah')(3000); 
describe("Does some testing", function() { 

    it("Fetches a blogpost by slug", function(done) { 
    r.get("/posts/aslug", function(res) { 
     expect(res.statusCode).to.equal(200); 
     expect(JSON.parse(res.body)["title"]).to.not.equal(null); 
     return done(); 
    }); 

    }); 
)); 

Odpowiedz

85

Nie sądzę kod związany baza danych może być odpowiednio przetestowany bez sprawdzając je za pomocą oprogramowania bazy danych. To dlatego, że testowany kod to nie tylko javascript, ale także ciąg zapytania do bazy danych. Nawet jeśli w twoim przypadku pytania wyglądają na proste, nie możesz liczyć na to, że będzie tak na zawsze.

Tak więc dowolna warstwa emulacji bazy danych musi koniecznie zaimplementować całą bazę danych (być może minus pamięć dyskowa). Do tego czasu kończysz testowanie integracji z emulatorem bazy danych, nawet jeśli nazywasz to testowaniem jednostkowym. Kolejną wadą jest to, że emulator bazy danych może w końcu mieć inny zestaw błędów w porównaniu do bazy danych i może skończyć się koniecznością kodowania zarówno emulatora bazy danych, jak i bazy danych (podobnie jak w przypadku IE vs Firefox vs Chrome itp.).

Dlatego, moim zdaniem, jedynym sposobem na poprawne przetestowanie kodu jest połączenie go z rzeczywistą bazą danych.

+1

Wiesz, robisz dobry punkt. Podczas gdy testy jednostkowe służą fenomenalnym celom (tj. Izolacji), masz mocny punkt do testowania integracji. –

+3

@MichaelPerrenoud: Podoba mi się zasada określona przez odpowiedź christkva: ** "Nie wyśmiewuj się z niczego, co nie posiadasz" **. Chociaż nie wyjaśnia szczegółowo, dlaczego jest to zły pomysł, jest to łatwa do zapamiętania reguła. – slebetman

+1

Nie zgadzam się z tą odpowiedzią, w meteorjach instalują testową bazę danych podczas wykonywania testów (zakładam, że nie jest to sztuczna biblioteka, ale tymczasowy plik) i jest to bardzo wygodne. Byłoby bardzo użyteczne mieć obiekt, który zachowuje się dokładnie jak monondy i czyści po sobie. Czy to wszystko w pamięci, czy plik tymczasowy, to szczegóły implementacji, więc nie trzeba powielać kodu. Zgadzam się, że ludzie, którzy robią kierowcę, powinni być tymi, którzy robią fałszywy obiekt. – Uri

36

Istnieje ogólna zasada, jeśli chodzi o kpin, która jest

Nie nic nie jesteś właścicielem drwić.

Jeśli chcesz wyśrubować bazę danych, ukryj ją za wyodrębnioną warstwę usługi i wyśmiewaj ją. Następnie sprawdź, czy integracja sprawdza rzeczywistą warstwę usługi.

Osobiście nie używam makiet do testowania i używam ich do projektowania od góry do dołu, pomagając mi rozwijać rozwój od początku do dołu, szyderując warstwy usług, kiedy je odwiedzam, a następnie ostatecznie wdrażając te warstwy i pisząc testy integracji . Używane jako narzędzie testowe sprawiają, że test jest bardzo kruchy, aw najgorszym przypadku prowadzi do rozbieżności między rzeczywistym zachowaniem a wyśmiewaniem.

+0

Pewnie, możesz ukryć to za repozytorium lub bramą i użyć symulatora, aby sterować testowym podejściem i izolować testy jednostek ... co to znaczy, że nie używasz mocków do testowania? Będziesz nadal trzymał tą fałszywą bramę/repozytorium w swoich testach, a potem użyjesz jakiegoś interfejsu do określenia rzeczywistej implementacji w twoim repozytorium za pomocą prawego interfejsu? – PositiveGuy

3

Moje preferowane podejście do testu jednostkowego kodu DB w dowolnym języku to dostęp do Mongo poprzez abstrakcję repozytorium (tutaj jest przykład http://iainjmitchell.com/blog/?p=884). Implementacje będą się różnić pod względem ujawnionej funkcjonalności bazy danych, ale poprzez usunięcie całego kodu Mongo z własnej logiki będziesz w stanie przejść do testu jednostkowego. Po prostu zastąp implementację repozytorium Mongo wersją zgaszoną, która jest banalnie prosta. Na przykład po prostu przechowuj obiekty w prostym zbiorze słowników w pamięci.

Dostaniesz zalety jednostki testującej swój własny kod w ten sposób bez zależności DB, ale nadal będziesz musiał wykonać testy integracji z główną bazą danych, ponieważ prawdopodobnie nigdy nie będziesz w stanie emulować specyficznych cech prawdziwego baza danych, jak powiedzieli tutaj inni. Rzeczy, które znalazłem są tak proste, jak indeksowanie w trybie bezpiecznym vs bez trybu awaryjnego. W szczególności, jeśli masz unikalny indeks, twoja sztuczna implementacja pamięci może to honorować we wszystkich przypadkach, ale Mongo nie będzie działać bez trybu awaryjnego.

Podczas gdy nadal będziesz musiał przetestować na bazie danych dla niektórych operacji, na pewno będziesz w stanie jednostkowo przetestować swoją własną logikę poprawnie z wdrożoną wersją Repozytorium.

+0

, ale w pewnym momencie twój prawdziwy kod implementacyjny musi odwoływać się do prawdziwych połączeń danych. Zakładam, że wstrzykujesz interfejs do swojego repozytorium na prawdziwy kod zapytania warstwy danych? – PositiveGuy

+0

Spróbuj użyć Dockera. Rozwijałem lata koszmarnych problemów konfiguracyjnych z bazami danych i instalacjami pakietów, używając Dockera do uruchamiania kontenerów z bazami danych zainicjowanymi danymi specyficznymi dla danego scenariusza. W rzeczywistości uruchamiam stosy 3 kontenerów: jeden z DB, jeden z kodem aplikacji i jeden z testowym sterownikiem. Jeśli Twój zestaw danych ma umiarkowany rozmiar, możesz nawet włączyć równoległe instancje tych stosów, znacznie skracając cykl testowania. – Raidex

32

Nie zgadzam się z wybraną odpowiedzią lub innymi odpowiedziami.

Czy nie byłoby wspaniale, gdyby można było złapać błędy spowodowane przez chaotyczne i wiele razy nieuporządkowane zmiany wprowadzone w schematach DB i kodzie, zanim dojdzie do kontroli jakości? Założę się, że większość będzie krzyczeć, że tak!

Z całą pewnością można i należy izolować i testować schematy DB. I nie robisz tego na podstawie emulatora lub ciężkiego obrazu lub odtwarzania twojego DB i maszyny. Właśnie takie rzeczy jak SQLite są tylko jednym przykładem. Kpisz sobie z niego na podstawie działającej w pamięci lekkiej instancji i ze statycznymi danymi, które nie zmieniają się w instancji pamięci, co oznacza, że ​​naprawdę testujesz swój DB w izolacji i możesz zaufać także swoim testom. I oczywiście jest szybki, ponieważ jest w pamięci, szkieletu i jest złomowany na końcu testu.

Tak, powinieneś i powinieneś przetestować SCHEMAT, który jest eksportowany do bardzo lekkiego egzemplarza pamięci dowolnego silnika DB/środowiska wykonawczego, którego używasz, i który wraz z dodaniem bardzo małej ilości danych statycznych staje się twoim izolowanym kpionym DB.

Eksportujesz swoje rzeczywiste schematy z prawdziwego DB okresowo (w sposób zautomatyzowany) i importujesz/aktualizujesz je do swojego instancji DB pamięci w świetle przed każdym push do QA i będziesz wiedział od razu, czy jakiekolwiek najnowsze zmiany DB wykonane przez twoją Administratorzy DB lub inni programiści, którzy ostatnio zmienili schemat, złamali wszelkie testy.

Podczas gdy cieszę się z wysiłków, aby spróbować odpowiedzieć na wszelkie możliwe pytania, głosowałbym na obecną odpowiedź, jeśli tylko mógłbym, ale jestem nowy i nie zbudowałem jeszcze wystarczająco dobrej reputacji, aby umożliwić mi to jeszcze.

Jeśli chodzi o osobę, która odpowiedziała słowami "nie wyśmiewaj niczego, czego nie posiadasz". Myślę, że chciał powiedzieć "nie testuj niczego, czego nie posiadasz". Ale wy drwicie z rzeczy, których nie macie! Ponieważ są to rzeczy, które nie są testowane, które trzeba odizolować!

Mam zamiar podzielić się z WAMI i zaktualizuję ten post w przyszłym momencie za pomocą prawdziwego przykładowego kodu JS!

To właśnie wiele zespołów testowych robi cały czas. Musisz tylko zrozumieć, w jaki sposób.

+8

wszelkie aktualizacje na temat tego, jak jeszcze? – ChickenWing24

+3

Chciałbym przegłosować, ale nie mogę, jeśli nie łagodzi to problemu i nie zapewnia rozwiązania. Zaktualizuj swój post, gdy masz szansę. – Shanimal

2

Miałem ten dylemat i zdecydowałem się pracować z testowym DB i czyścić go za każdym razem, gdy zaczyna się test. (jak upuścić wszystko: https://stackoverflow.com/a/25639377/378594)

Za pomocą NPM można nawet utworzyć skrypt testowy, który tworzy plik db i czyści go po.

+0

To jest naprawdę przyjemne podejście i poleciłbym każdemu, kto wykonałby poważne pipelining CI/CD, aby to zrobić. Dzięki dzisiejszym narzędziom JavaScript jesteśmy w stanie łatwo tworzyć i upuszczać bazy testowe przed i po uruchomieniu testów. Zastanowiłbym się, czy to podejście jest odpowiednie podczas tworzenia (nie chcesz upuszczać i tworzyć bazy danych przy każdej zmianie kodu), ale jest inne rozwiązanie.Przynajmniej rozwiązuje problem konieczności utrzymywania oddzielnych integracji wtyczek, które kpią z danych i przyklejają je do twojego środowiska testowego. – Nicky

4

Co ?! Po co więc drwić z niczego? Celem kpiny jest pominięcie złożoności i testowanie własnego kodu jednostki. Jeśli chcesz pisać testy e2e, użyj db.

Pisanie kodu do konfiguracji/rozbiórki Testowanie DB dla testów jednostkowych to dług techniczny i niezwykle niesatysfakcjonujący.

Istnieje mock biblioteki w KMP:

Mongo - https://www.npmjs.com/package/mongomock

mangusta - https://www.npmjs.com/package/mockgoose

Jeśli te nie obsługują funkcje potrzebne, to tak może być konieczne do korzystania z prawdziwych .

+1

lol "mockgoose" top 5 najśmieszniejszych nazw pakietu NPM imo –

+0

IMHO lepiej jest udawać niż symulować - https://jsmockito.org/ –

Powiązane problemy