我目前正在尝试测试一段代码,以便在放入新实体之前在数据存储上运行查询,以确保不创建重复项。我编写的代码在应用程序上下文中运行良好,但是我为该方法编写的测试失败。似乎我无法通过测试包上下文中的查询访问放入数据存储区的数据。
一种可能性在于从输出goapp test内容如下:Applying all pending transactions and saving the datastore。在调用get和put方法之后,此行将打印出来(我使用log语句对此进行了验证)。
goapp test
Applying all pending transactions and saving the datastore
我尝试关闭上下文并为不同的操作创建一个新的上下文,但是不幸的是,这也没有帮助。下面是一个简单的测试用例,它放入一个对象,然后在该对象上运行查询。任何帮助,将不胜感激。
type Entity struct { Value string } func TestEntityQuery(t *testing.T) { c, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer c.Close() key := datastore.NewIncompleteKey(c, "Entity", nil) key, err = datastore.Put(c, key, &Entity{Value: "test"}) if err != nil { t.Fatal(err) } q := datastore.NewQuery("Entity").Filter("Value =", "test") var entities []Entity keys, err := q.GetAll(c, &entities) if err != nil { t.Fatal(err) } if len(keys) == 0 { t.Error("No keys found in query") } if len(entities) == 0 { t.Error("No entities found in query") } }
您的测试代码没有错。问题出在数据存储区本身。HR数据存储中的大多数查询不是“立即一致”的,而是最终一致的。您可以在数据存储区文档中阅读有关此内容的更多信息。
因此,基本上发生的事情是将实体放入数据存储区,而SDK的数据存储区“模拟”了在生产中可以观察到的延迟,因此,如果在此之后立即运行查询(这不是祖先查询),则该查询结果将不包括您刚刚保存的新实体。
如果您在datastore.Put()和之间放置了几秒钟的睡眠q.GetAll(),您将看到测试通过。试试吧。在我的测试中,仅睡100毫秒就足够了,并且测试始终通过。但是在编写针对此类情况的测试时,请使用StronglyConsistentDatastore: true在JonhGB的答案中可以看到的选项。
datastore.Put()
q.GetAll()
StronglyConsistentDatastore: true
如果您使用Ancestor查询,因为它们是高度一致的,那么您也会看到测试通过且没有睡眠。