Pada modul ini kita akan membuat tahap awal dari test yaitu mematikan dan menyalakan docker dari fungsi test dengan database kosong didalamnya.
Buat test file pkg/repository/dbrebo/users_postgres_test.go. Gunakan kode berikut
package dbrepo
import (
"database/sql"
"fmt"
"log"
"os"
"testing"
_ "github.com/jackc/pgconn"
_ "github.com/jackc/pgx/v4"
_ "github.com/jackc/pgx/v4/stdlib"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
)
var (
host = "localhost"
user = "postgres"
password = "postgres"
dbName = "users_test"
port = "5435"
dsn = "host=%s port=%s user=%s password=%s dbname=%s sslmode=disable timezone=UTC connect_timeout=5"
)
var resource *dockertest.Resource
var pool *dockertest.Pool
var testDB *sql.DB
func TestMain(m *testing.M) {
// connect to docker; fail if docker not running
p, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("could not connect to docker; is it running? %s", err)
}
pool = p
// set up our docker options, specifying the image and so forth
opts := dockertest.RunOptions{
Repository: "postgres",
Tag: "14.5",
Env: []string{
"POSTGRES_USER=" + user,
"POSTGRES_PASSWORD=" + password,
"POSTGRES_DB=" + dbName,
},
ExposedPorts: []string{"5432"},
PortBindings: map[docker.Port][]docker.PortBinding{
"5432": {
{HostIP: "0.0.0.0", HostPort: port},
},
},
}
// get a resource (docker image)
resource, err = pool.RunWithOptions(&opts)
if err != nil {
_ = pool.Purge(resource)
log.Fatalf("could not start resource: %s", err)
}
// start the image and wait until it's ready
if err := pool.Retry(func() error {
var err error
testDB, err = sql.Open("pgx", fmt.Sprintf(dsn, host, port, user, password, dbName))
if err != nil {
log.Println("Error:", err)
return err
}
return testDB.Ping()
}); err != nil {
_ = pool.Purge(resource)
log.Fatalf("could not connect to database: %s", err)
}
// populate the database with empty tables
err = createTables()
if err != nil {
log.Fatalf("error creating tables: %s", err)
}
// run tests
code := m.Run()
// clean up
if err := pool.Purge(resource); err != nil {
log.Fatalf("could not purge resource: %s", err)
}
os.Exit(code)
}
func createTables() error {
tableSQL, err := os.ReadFile("./testdata/users.sql")
if err != nil {
fmt.Println(err)
return err
}
_, err = testDB.Exec(string(tableSQL))
if err != nil {
fmt.Println(err)
return err
}
return nil
}
func Test_pingDB(t *testing.T) {
err := testDB.Ping()
if err != nil {
t.Error("can't ping database")
}
}
Kemudian buat folder testdata didalam folder pkg/repository/dbrepo, buat file users.sql
File sql ini dimodifikasi dari file sql yang digunakan dalam aplikasi, berguna untuk membuat empty database untuk fungsi test.
CREATE TABLE public.user_images (
id integer NOT NULL,
user_id integer,
file_name character varying(255),
created_at timestamp without time zone,
updated_at timestamp without time zone
);
--
-- Name: user_images_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
ALTER TABLE public.user_images ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
SEQUENCE NAME public.user_images_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
--
-- Name: users; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.users (
id integer NOT NULL,
first_name character varying(255),
last_name character varying(255),
email character varying(255),
password character varying(60),
is_admin integer,
created_at timestamp without time zone,
updated_at timestamp without time zone
);
--
-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
ALTER TABLE public.users ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
SEQUENCE NAME public.users_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1
);
--
-- Name: user_images user_images_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.user_images
ADD CONSTRAINT user_images_pkey PRIMARY KEY (id);
--
-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
--
-- Name: user_images user_images_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.user_images
ADD CONSTRAINT user_images_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE CASCADE;
--
-- PostgreSQL database dump complete
--
Sebelum menjalankan test, pastikan instance container untuk webapp telah dihapus. Buka command prompt, masuk ke root directory dari webapp.
$ docker-compose down
Setelah docker container webapp down, kita bisa jalankan test, namun sampai disini tidak akan ada efek apapun, karena hanya menyalakan docker container, membuat database kosong, lalu mematikan docker container lagi.
Pada modul selanjutnya kita akan buat test untuk fungsi-fungsi database.