How to test an app that logs zap.Strings fields #1210
-
Here is a minimal working example. I want to assert that the field is set to the correct value. But it is not comparable because the types are different. import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
)
func Test(t *testing.T) {
observedZapCore, observedLogs := observer.New(zap.DebugLevel)
observedLogger := zap.New(observedZapCore)
observedLogger.Info("log strings",
zap.Strings("scopes", []string{"scope1", "scope2"}))
log := observedLogs.All()[0]
assert.ElementsMatch(t, []zap.Field{
{Key: "scopes", Type: zapcore.ArrayMarshalerType, Interface: []interface{}{"scope1", "scope2"}},
}, log.Context)
} pls excuse my bad english |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Hey @slashformotion, You can use LoggedEntry.ContextMap to get a assert.ElementsMatch(t, []interface{}{"scope1", "scope2"}, log.ContextMap()["scopes"]) Asserting on the Using Field directly You can still operate directly on it if you prefer, you just have to interpret it per the contract of For example, extract the field and verify its other attributes: field := log.Context[0]
require.Equal(t, "scopes", field.Key)
require.Equal(t, zapcore.ArrayMarshalerType, field.Type) Then, extract the ArrayMarshaler and pass it into a MapObjectEncoder.AddArray: enc := zapcore.NewMapObjectEncoder()
enc.AddArray("x", field.Interface.(zapcore.ArrayMarshaler)) This records the values into the MapObjectEncoder's assert.Equal(t, []interface{}{"scope1", "scope2"}, enc.Fields["x"]) (Note that this is almost the same thing as using |
Beta Was this translation helpful? Give feedback.
Hey @slashformotion,
You can use LoggedEntry.ContextMap to get a
map[string]interface{}
to compare against. This will contain only primitive values:Asserting on the
Field
directly means you're dealing with Zap's internal representation.Using Field directly
You can still operate directly on it if you prefer, you just have to interpret it per the contract of
Field
.In this case, for example: if the type is ArrayMarshalerType,
the only thing that's part of the public contract is that
Interface
holds azapcore.ArrayMarshaler
.So you have to interpret that with a custom ArrayEncoder, or with the MapObjectE…