Skip to content

Commit 4a55aa4

Browse files
test: mongodb custom built-ins unit tests (#436)
* test: mongodb utilities test refactor * test: mongodb custom builtins tests
1 parent 52042fd commit 4a55aa4

File tree

2 files changed

+135
-31
lines changed

2 files changed

+135
-31
lines changed

custom_builtins/mongo.go

+33-31
Original file line numberDiff line numberDiff line change
@@ -38,39 +38,41 @@ var MongoFindOne = rego.Function2(
3838
Name: MongoFindOneDecl.Name,
3939
Decl: MongoFindOneDecl.Decl,
4040
},
41-
func(ctx rego.BuiltinContext, collectionNameTerm, queryTerm *ast.Term) (*ast.Term, error) {
42-
mongoClient, err := GetMongoClientFromContext(ctx.Context)
43-
if err != nil {
44-
return nil, err
45-
}
46-
if mongoClient == nil {
47-
return nil, fmt.Errorf("mongo client not set")
48-
}
49-
50-
var collectionName string
51-
if err := ast.As(collectionNameTerm.Value, &collectionName); err != nil {
52-
return nil, err
53-
}
54-
55-
query := make(map[string]interface{})
56-
if err := ast.As(queryTerm.Value, &query); err != nil {
57-
return nil, err
58-
}
59-
60-
result, err := mongoClient.FindOne(ctx.Context, collectionName, query)
61-
if err != nil {
62-
return nil, err
63-
}
64-
65-
t, err := ast.InterfaceToValue(result)
66-
if err != nil {
67-
return nil, err
68-
}
69-
70-
return ast.NewTerm(t), nil
71-
},
41+
mongoFindOneDef,
7242
)
7343

44+
func mongoFindOneDef(ctx rego.BuiltinContext, collectionNameTerm, queryTerm *ast.Term) (*ast.Term, error) {
45+
mongoClient, err := GetMongoClientFromContext(ctx.Context)
46+
if err != nil {
47+
return nil, err
48+
}
49+
if mongoClient == nil {
50+
return nil, fmt.Errorf("mongo client not set")
51+
}
52+
53+
var collectionName string
54+
if err := ast.As(collectionNameTerm.Value, &collectionName); err != nil {
55+
return nil, err
56+
}
57+
58+
query := make(map[string]interface{})
59+
if err := ast.As(queryTerm.Value, &query); err != nil {
60+
return nil, err
61+
}
62+
63+
result, err := mongoClient.FindOne(ctx.Context, collectionName, query)
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
t, err := ast.InterfaceToValue(result)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
return ast.NewTerm(t), nil
74+
}
75+
7476
var MongoFindManyDecl = &ast.Builtin{
7577
Name: "find_many",
7678
Decl: types.NewFunction(

custom_builtins/mongo_test.go

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2025 Mia srl
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package custom_builtins
16+
17+
import (
18+
"context"
19+
"errors"
20+
"testing"
21+
22+
"github.com/open-policy-agent/opa/ast"
23+
"github.com/open-policy-agent/opa/rego"
24+
"github.com/rond-authz/rond/custom_builtins/mocks"
25+
"github.com/stretchr/testify/require"
26+
)
27+
28+
func prepareContext(t *testing.T, mongoClientMock *mocks.MongoClientMock) rego.BuiltinContext {
29+
t.Helper()
30+
31+
ctx := context.Background()
32+
33+
if mongoClientMock != nil {
34+
ctx = WithMongoClient(ctx, mongoClientMock)
35+
}
36+
37+
return rego.BuiltinContext{
38+
Context: ctx,
39+
}
40+
}
41+
42+
func TestMongoFindOneDefinition(t *testing.T) {
43+
defaultMock := &mocks.MongoClientMock{}
44+
45+
t.Run("returns error if mongo client is not set", func(t *testing.T) {
46+
_, err := mongoFindOneDef(
47+
prepareContext(t, nil),
48+
nil,
49+
nil,
50+
)
51+
require.ErrorContains(t, err, "mongo client not set")
52+
})
53+
54+
t.Run("returns error if mongo client in context is not valid", func(t *testing.T) {
55+
_, err := mongoFindOneDef(
56+
rego.BuiltinContext{
57+
Context: context.WithValue(context.Background(), mongoClientCustomBuiltinContextKey{}, "not a valid client"),
58+
},
59+
nil,
60+
nil,
61+
)
62+
require.ErrorContains(t, err, "no MongoDB client found in context")
63+
})
64+
65+
t.Run("returns error if collection name is not a string", func(t *testing.T) {
66+
_, err := mongoFindOneDef(
67+
prepareContext(t, defaultMock),
68+
ast.BooleanTerm(false),
69+
nil,
70+
)
71+
require.ErrorContains(t, err, "cannot unmarshal bool")
72+
})
73+
74+
t.Run("returns error if query is not an object", func(t *testing.T) {
75+
_, err := mongoFindOneDef(prepareContext(
76+
t,
77+
defaultMock),
78+
ast.StringTerm("coll"),
79+
ast.BooleanTerm(false),
80+
)
81+
require.ErrorContains(t, err, "cannot unmarshal bool")
82+
})
83+
84+
t.Run("returns error if FindOne returns an error", func(t *testing.T) {
85+
assertionInvoked := false
86+
mock := &mocks.MongoClientMock{
87+
FindOneError: errors.New("some error"),
88+
FindOneExpectation: func(collectionName string, query interface{}) {
89+
assertionInvoked = true
90+
require.Equal(t, "coll", collectionName)
91+
require.Equal(t, map[string]interface{}{}, query)
92+
},
93+
}
94+
_, err := mongoFindOneDef(
95+
prepareContext(t, mock),
96+
ast.StringTerm("coll"),
97+
ast.MustParseTerm("{}"),
98+
)
99+
require.ErrorContains(t, err, "some error")
100+
require.True(t, assertionInvoked)
101+
})
102+
}

0 commit comments

Comments
 (0)