func TestLoadBatchFromDatastore(t *testing.T) { gaeCtx, _ := aetest.NewContext(nil) defer gaeCtx.Close() Convey("Given I have a load batch from datastore transformer", t, func() { riversCtx := rivers.NewContext() loadBatchProcessor := appx.NewStep(riversCtx).LoadBatchFromDatastore(gaeCtx) Convey("And I have a few entities in datastore", func() { user1 := NewUser(User{ Name: "Borges", Email: "*****@*****.**", SSN: "123123123", }) user2 := NewUser(User{ Name: "Borges", Email: "*****@*****.**", SSN: "123123123", }) err := appx.NewKeyResolver(gaeCtx).Resolve(user1) So(err, ShouldBeNil) err = appx.NewKeyResolver(gaeCtx).Resolve(user2) So(err, ShouldBeNil) _, err = datastore.Put(gaeCtx, user1.Key(), user1) So(err, ShouldBeNil) _, err = datastore.Put(gaeCtx, user2.Key(), user2) So(err, ShouldBeNil) Convey("When I transform the incoming batch", func() { userFromDatastore1 := NewUser(User{Name: user1.Name}) userFromDatastore2 := NewUser(User{Name: user2.Name}) appx.NewKeyResolver(gaeCtx).Resolve(userFromDatastore1) appx.NewKeyResolver(gaeCtx).Resolve(userFromDatastore2) batch := &appx.DatastoreBatch{ Size: 2, Keys: []*datastore.Key{ userFromDatastore1.Key(), userFromDatastore2.Key(), }, Items: []appx.Entity{ userFromDatastore1, userFromDatastore2, }, } loadBatchProcessor(batch) Convey("And entities are loaded from datastore", func() { So(userFromDatastore1, ShouldResemble, user1) So(userFromDatastore2, ShouldResemble, user2) }) }) }) }) }
func TestLoadBatchFromCache(t *testing.T) { gaeCtx, _ := aetest.NewContext(nil) defer gaeCtx.Close() Convey("Given I have a load batch from cache transformer", t, func() { riversCtx := rivers.NewContext() loadBatchProcessor := appx.NewStep(riversCtx).LoadBatchFromCache(gaeCtx) Convey("And I have a few entities in the cache", func() { user1 := NewUser(User{ Name: "Borges", Email: "*****@*****.**", SSN: "123123123", }) user2 := NewUser(User{ Name: "Diego", Email: "*****@*****.**", SSN: "321321", }) appx.NewKeyResolver(gaeCtx).Resolve(user1) appx.NewKeyResolver(gaeCtx).Resolve(user2) memcache.JSON.Set(gaeCtx, &memcache.Item{ Key: user1.CacheID(), Object: appx.CachedEntity{ Entity: user1, Key: user1.Key(), }, }) memcache.JSON.Set(gaeCtx, &memcache.Item{ Key: user2.CacheID(), Object: appx.CachedEntity{ Entity: user2, Key: user2.Key(), }, }) Convey("When I transform the incoming batch", func() { notCachedUser := NewUser(User{ Name: "not cached", SSN: "notcached", }) userFromCache1 := NewUser(User{Name: user1.Name}) userFromCache2 := NewUser(User{Name: user2.Name}) batchItems := make(map[string]*appx.CachedEntity) batchItems[user1.CacheID()] = &appx.CachedEntity{ Entity: userFromCache1, } batchItems[user2.CacheID()] = &appx.CachedEntity{ Entity: userFromCache2, } batchItems[notCachedUser.CacheID()] = &appx.CachedEntity{ Entity: notCachedUser, } batch := &appx.MemcacheLoadBatch{ Keys: []string{user1.CacheID(), user2.CacheID()}, Items: batchItems, } in, out := stream.New(1) loadBatchProcessor(batch, stream.NewEmitter(rivers.NewContext(), out)) close(out) Convey("Then cache misses are sent downstream", func() { So(in.ReadAll(), ShouldResemble, []stream.T{notCachedUser}) Convey("And entities are loaded from cache", func() { So(userFromCache1, ShouldResemble, user1) So(userFromCache2, ShouldResemble, user2) }) }) }) }) }) }
func TestQueryEntityFromDatastore(t *testing.T) { gaeCtx, _ := aetest.NewContext(nil) defer gaeCtx.Close() user := &User{ Name: "Borges", Email: "*****@*****.**", SSN: "123123123", keySpec: &appx.KeySpec{ Kind: "Users", StringID: "borges", }, } parentKey := datastore.NewKey(gaeCtx, "Parent", "parent id", 0, nil) user.SetParentKey(parentKey) Convey("Given I have a query entity from datastore transformer", t, func() { riversCtx := rivers.NewContext() queryProcessor := appx.NewStep(riversCtx).QueryEntityFromDatastore(gaeCtx) Convey("When I transform the inbound stream with non existent entity", func() { nonExistentUser := &User{ Email: "*****@*****.**", keySpec: &appx.KeySpec{ Kind: "Users", }, } runQuery := func() { queryProcessor(nonExistentUser) } Convey("Then query processor panics", func() { So(runQuery, ShouldPanic) }) }) Convey("And I have an entity in datastore", func() { err := appx.NewKeyResolver(gaeCtx).Resolve(user) So(err, ShouldBeNil) _, err = datastore.Put(gaeCtx, user.Key(), user) So(err, ShouldBeNil) // Give datastore some time so that the created entity is available to be queried time.Sleep(200 * time.Millisecond) Convey("When I transform the inbound stream", func() { userFromDatastore := &User{ Email: "*****@*****.**", keySpec: &appx.KeySpec{ Kind: "Users", }, } queryProcessor(userFromDatastore) Convey("And queryable entities are loaded from datastore", func() { So(userFromDatastore.Name, ShouldEqual, user.Name) So(userFromDatastore.Email, ShouldEqual, user.Email) So(userFromDatastore.Key(), ShouldResemble, user.Key()) So(userFromDatastore.ParentKey(), ShouldResemble, user.ParentKey()) }) }) }) }) }