GAE Go测试-数据存储区查询是否可以在测试环境中工作?

Recently I started writing some tests for sending emails in my Google App Engine Go application. Part of the email sending process is saving the email in the datastore with this function:

func PutInDatastoreFull(c appengine.Context, kind, stringID string, intID int64, parent *datastore.Key, variable interface{}) (*datastore.Key, error) {
    k := datastore.NewKey(c, kind, stringID, intID, parent)
    key, err := datastore.Put(c, k, variable)
    return key, err
}

My tests query the datastore with this function:

func QueryGetAllWithLimit(c appengine.Context, kind string, limit int, dst interface{}) ([]*datastore.Key, error) {
    q := datastore.NewQuery(kind).Limit(limit)
    return q.GetAll(c, dst)
}

When I run it in development environment, it returns last emails without a problem. However, when I run it with goapp test, it returns no error and no data. Is this an expected behaviour for the testing environment, or did I just find some bug?

EDIT:

The test is:

//Testing file
func TestEmails(t *testing.T) {
    c, err := aetest.NewContext(nil)
    if err != nil {
        t.Fatal(err)
    }
    defer c.Close()

    err := NotifyAdminOfLowBalance(c, []string{"WARNING1", "WARNING2"})
    if err != nil {
        t.Fatal(err)
    }
    emails, err := Data.LoadLastEmails(c, 100)
    if err != nil {
        t.Fatal(err)
    }
    if len(emails) == 0 { //test fails here
        t.Fatal("len(emails)==0")
    }
}

//Production code
func NotifyAdminOfLowBalance(c appengine.Context, warnings []string) error {
    not := Notification{}
    not.Warnings = warnings

    buff := new(bytes.Buffer)
    err := LowBalanceTemplate.Execute(buff, not);
    if err != nil {
        c.Errorf("Backend Notifications - NotifyAdminOfLowBalance - error 1 - %v", err)
        return err
    }
    emailBody := buff.String()
    c.Debugf("Backend Notifications - emailBody - %v", emailBody)
    emailSubject := "Low balance!"
    err = Email.SendHTMLEmail(c, emailSubject, DEFINE.AdminEmails, DEFINE.EmailSender, emailBody)
    if err != nil {
        c.Errorf("Backend Notifications - NotifyAdminOfLowBalance - error 2 - %v", err)
        return err
    }
    err = Data.CreateAndSaveEmail(c, emailBody, emailSubject, "ADMIN", "", "", "")
    if err != nil {
        c.Errorf("Backend Notifications - NotifyAdminOfLowBalance - error 3 - %v", err)
        return err
    }
    return nil
}



//Data/Email.go file:
var EmailStr string = "Email"

type Email struct {
    //Class for handling Emails of what is happening in the system
    EmailID           string //ISO date?
    Timestamp         time.Time
    Body              string `datastore:"-"`
    BodyByte          []byte
    Subject           string
    UserEmail         string
    RippleTxID        string
    CoinTxID          string
    Currency          string
}

func (l *Email) LoadStrings() {
    l.Body = mymath.Hex2ASCII(l.BodyByte)
}

func CreateAndSaveEmail(c appengine.Context, body, subject, userEmail, rippleTx, coinTx, currency string) error {
    email := new(Email)
    email.Timestamp = time.Now()
    email.EmailID = email.Timestamp.Format("2006-01-02T15:04:05:")+mymath.Int2Str(email.Timestamp.Nanosecond())
    email.Body = body
    email.BodyByte = mymath.ASCII2Hex(body)
    email.Subject = subject
    email.UserEmail = userEmail
    email.RippleTxID = rippleTx
    email.CoinTxID = coinTx
    email.Currency = currency

    keys, err := Datastore.PutInDatastoreFull(c, EmailStr, email.EmailID, 0, nil, email)
    c.Debugf("keys - %v, err - %v", keys, err)
    if err != nil {
        c.Errorf("Email - CreateAndSaveEmail error 1 - %v", err)
        return err
    }
    return nil
}

func LoadLastEmails(c appengine.Context, count int) ([]Email, error) {
    c.Debugf("LoadLastEmails - %v", count)
    dst := []Email{}
    keys, err := Datastore.QueryGetAllWithLimit(c, EmailStr, count, &dst)
    c.Debugf("keys - %v, err - %v", keys, err)
    if err != nil {
        c.Errorf("Email - LoadLastEmails error 1 - %v", err)
        return nil, err
    }
    c.Debugf("dst - %v", dst)
    return dst, nil
}

And the Datastore functions were already included above

I ran into this too and I believe it to be because you are doing a cross group query and the write has not been applied yet. I was able to reproduce this with the dev server too if I made a put then a query right after. I understand this to be how the dev server simulates production-like write visibility when you are not in a transaction or entity group. IOW, I think it's working as it should.

Adding a sleep between your calls (a bad idea) or performing a get() on any of the entities that had previously changed/created in the test will make them show up in the query.

For writes and data visibility rules see: https://developers.google.com/appengine/docs/go/datastore/#Go_Datastore_writes_and_data_visibility