You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of the easymongo refactor (see PLAN.md on the refactor branch). This is where the helpers that used to live in mongotest (EasyMongoWithContainer, the TestConnection that embedded *easymongo.Connection) now live, so the module dependency is one-way: easymongo depends on mongotest, never the reverse.
Working context (read this first)
Repository github.com/tophergopher/easymongo. Start from branch claude/mongotest-easymongo-refactor-wu2vhm; create a branch issue-<number>-<short-slug> from it and open a pull request back into it. PLAN.md on that branch is the source of truth; read it before writing code.
Go project, single module, all packages at the repo root except the new easymongotest/ subpackage. The final toolchain target is Go 1.27 (set by Toolchain: go 1.27, latest dependencies, tidy, remove replace directives #10); any Go 1.24 or newer works until then. Before pushing: gofmt -l . prints nothing, go vet ./..., go test -race ./....
The existing test suite (*_test.go at the root, package easymongo_test, every test function calling setup(t) from common_test.go) is the regression net for this refactor. It must pass after your change. It needs a Docker daemon reachable through the normal Docker environment and the mongo:8 image.
Method is test-driven: write the tests listed under "Tests first", confirm they fail for the expected reason, then implement. Never delete, skip or weaken an existing test to get green; if a test must change because the public API changed (for example primitive.ObjectID to bson.ObjectID), change only the types.
Commit messages: imperative summary line, blank line, body explaining why. Mention this issue number in the pull request description.
Scope
Package github.com/tophergopher/easymongo/easymongotest inside the easymongo module (a subpackage, not a separate module), requiring github.com/tophergopher/mongotest/v2:
typeTestConnectionstruct {
*easymongo.ConnectionMongo*mongotest.Instance// the underlying mongotest/v2 instance (container + driver client)
}
funcStart(ctx context.Context, opts...mongotest.Option) (*TestConnection, error)
funcRun(tb testing.TB, opts...mongotest.Option) *TestConnection// tb.Fatal on error, tb.Cleanup(Stop)func (tc*TestConnection) Stop(ctx context.Context) error// Disconnect easymongo, then Mongo.Stop// Convenience wrappers migrated from mongotest, documented as plain wrappers (not deprecated):funcNewTestConnection(spinupDockerContainerbool) (*TestConnection, error)
func (tc*TestConnection) KillMongoContainer() errorfuncWithContainer(ffunc(*easymongo.Connection) error) error// was mongotest.EasyMongoWithContainer
Start builds the easymongo connection with easymongo.ConnectWith(inst.URI()), applying .TLSConfig(inst.Container.TLSConfig()) when the instance is in TLS mode, then .Connect(). Because easymongo caches the last connection globally, Start documents that side effect.
Because this is a subpackage of the easymongo module, github.com/tophergopher/mongotest/v2 becomes a regular requirement in easymongo's go.mod. It is small (driver v2 plus the root mongotest module) and is only compiled by importers of easymongotest. Document this in the package doc.
Package doc with a full example test.
Implementation details
Files: easymongotest/doc.go, easymongotest/easymongotest.go, easymongotest/compat.go (the migrated wrappers), easymongotest/easymongotest_test.go, easymongotest/example_test.go.
Import of the container library: mongotest "github.com/tophergopher/mongotest/v2". Until that module is tagged, go.mod gets replace github.com/tophergopher/mongotest/v2 => ../mongotest/v2 (a sibling checkout of the mongotest repo on its refactor branch); this is temporary and removed by #10.
Only these members of mongotest.Instance / mongod.Container are used here: Start(ctx, opts...), Run(tb, opts...), inst.URI(), inst.Container (may be nil for attached instances), inst.Container.TLSConfig() (nil when TLS is off), inst.Stop(ctx). easymongo itself may still be on driver v1 when this lands; that is fine because none of the driver types of mongotest's embedded client are touched here.
Stop calls Connection.Disconnect (from #6; if #6 has not landed, call MongoDriverClient().Disconnect(ctx) directly) and then Mongo.Stop(ctx), and is idempotent.
To verify in a test that the container is gone after WithContainer, build a client with github.com/tophergopher/mongotest/dockerapi and check the error with the shared helper in github.com/tophergopher/mongotest/dockerclient: c, _ := dockerapi.FromEnv(); _, err := c.ContainerInspect(ctx, id); require.True(t, dockerclient.IsNotFound(err), "the container must be gone once WithContainer returns"). The Docker client is an interface (dockerclient.Client) with dockerapi as the default implementation; dockerapi.IsNotFound still exists as an alias, but new code should name dockerclient.
Tests first (easymongotest/easymongotest_test.go, integration against Docker)
Run(t) then conn.D("db").C("c").Insert().One(...) and Find(...).One(...) round-trip.
WithContainer runs the callback and the container is gone afterwards (capture Mongo.Container.ID() through a pointer, then inspect it with a dockerapi client and assert dockerclient.IsNotFound).
NewTestConnection(true) then KillMongoContainer() works; KillMongoContainer twice returns nil.
TLS: Run(t, mongotest.WithTLS()) inserts and reads.
Replica set: Run(t, mongotest.WithReplicaSet("rs0")) and a simple insert succeed.
Acceptance
go test ./easymongotest/... passes against Docker.
Importing only github.com/tophergopher/easymongo in a scratch program does not compile any mongotest, dockerclient, dockerapi or dockermock package (go list -deps).
Depends on: TopherGopher/mongotest#42 (use the local replace described above until it is tagged). Does not depend on any driver v2 change in this repository.
Part of the easymongo refactor (see
PLAN.mdon the refactor branch). This is where the helpers that used to live in mongotest (EasyMongoWithContainer, theTestConnectionthat embedded*easymongo.Connection) now live, so the module dependency is one-way: easymongo depends on mongotest, never the reverse.Working context (read this first)
github.com/tophergopher/easymongo. Start from branchclaude/mongotest-easymongo-refactor-wu2vhm; create a branchissue-<number>-<short-slug>from it and open a pull request back into it.PLAN.mdon that branch is the source of truth; read it before writing code.easymongotest/subpackage. The final toolchain target is Go 1.27 (set by Toolchain: go 1.27, latest dependencies, tidy, remove replace directives #10); any Go 1.24 or newer works until then. Before pushing:gofmt -l .prints nothing,go vet ./...,go test -race ./....*_test.goat the root, packageeasymongo_test, every test function callingsetup(t)fromcommon_test.go) is the regression net for this refactor. It must pass after your change. It needs a Docker daemon reachable through the normal Docker environment and themongo:8image.*mongo.Clienttype flows fromConnectiontoDatabasetoCollection), so the four driver issues Driver v2: migrate connect.go (mongo.Connect, Disconnect, BSONOptions, write concern) #2, Driver v2: options struct literals become builders; drop MaxTime; ArrayFilters and Delete option changes #3, Driver v2: primitive package merged into bson; replace x/bsonx in index.go #4 and Driver v2: Distinct returns a DistinctResult that must be decoded #5 land together in one pull request, worked in that order. Before them, New easymongotest subpackage wrapping mongotest/v2 #7 and Switch the easymongo test suite to easymongotest #8 must land so the test suite no longer depends on the oldgithub.com/tophergopher/mongotestv0.1.0 module (which itself imports easymongo and breaks the moment easymongo's types change). Until mongotest'sv2module is tagged, use a localreplace github.com/tophergopher/mongotest/v2 => ../mongotest/v2ingo.modand say so in the pull request; Toolchain: go 1.27, latest dependencies, tidy, remove replace directives #10 removes it.primitive.ObjectIDtobson.ObjectID), change only the types.Scope
Package
github.com/tophergopher/easymongo/easymongotestinside the easymongo module (a subpackage, not a separate module), requiringgithub.com/tophergopher/mongotest/v2:Startbuilds the easymongo connection witheasymongo.ConnectWith(inst.URI()), applying.TLSConfig(inst.Container.TLSConfig())when the instance is in TLS mode, then.Connect(). Because easymongo caches the last connection globally,Startdocuments that side effect.github.com/tophergopher/mongotest/v2becomes a regular requirement in easymongo'sgo.mod. It is small (driver v2 plus the root mongotest module) and is only compiled by importers ofeasymongotest. Document this in the package doc.Implementation details
Files:
easymongotest/doc.go,easymongotest/easymongotest.go,easymongotest/compat.go(the migrated wrappers),easymongotest/easymongotest_test.go,easymongotest/example_test.go.Import of the container library:
mongotest "github.com/tophergopher/mongotest/v2". Until that module is tagged,go.modgetsreplace github.com/tophergopher/mongotest/v2 => ../mongotest/v2(a sibling checkout of the mongotest repo on its refactor branch); this is temporary and removed by #10.Only these members of
mongotest.Instance/mongod.Containerare used here:Start(ctx, opts...),Run(tb, opts...),inst.URI(),inst.Container(may be nil for attached instances),inst.Container.TLSConfig()(nil when TLS is off),inst.Stop(ctx). easymongo itself may still be on driver v1 when this lands; that is fine because none of the driver types of mongotest's embedded client are touched here.StopcallsConnection.Disconnect(from #6; if #6 has not landed, callMongoDriverClient().Disconnect(ctx)directly) and thenMongo.Stop(ctx), and is idempotent.To verify in a test that the container is gone after
WithContainer, build a client withgithub.com/tophergopher/mongotest/dockerapiand check the error with the shared helper ingithub.com/tophergopher/mongotest/dockerclient:c, _ := dockerapi.FromEnv(); _, err := c.ContainerInspect(ctx, id); require.True(t, dockerclient.IsNotFound(err), "the container must be gone once WithContainer returns"). The Docker client is an interface (dockerclient.Client) withdockerapias the default implementation;dockerapi.IsNotFoundstill exists as an alias, but new code should namedockerclient.Tests first (
easymongotest/easymongotest_test.go, integration against Docker)Run(t)thenconn.D("db").C("c").Insert().One(...)andFind(...).One(...)round-trip.WithContainerruns the callback and the container is gone afterwards (captureMongo.Container.ID()through a pointer, then inspect it with adockerapiclient and assertdockerclient.IsNotFound).NewTestConnection(true)thenKillMongoContainer()works;KillMongoContainertwice returns nil.Run(t, mongotest.WithTLS())inserts and reads.Run(t, mongotest.WithReplicaSet("rs0"))and a simple insert succeed.Acceptance
go test ./easymongotest/...passes against Docker.github.com/tophergopher/easymongoin a scratch program does not compile anymongotest,dockerclient,dockerapiordockermockpackage (go list -deps).Depends on: TopherGopher/mongotest#42 (use the local
replacedescribed above until it is tagged). Does not depend on any driver v2 change in this repository.