mockkit

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 28, 2024 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Example (Behaviour_passed)
registry := UserRegistry_Spec{
	Get: UserRegistry_Get_Expects(its.StringHavingPrefix("user-id:")).
		ThenReturn(
			example.User{Id: "user-id:abcde", Name: "John Doe"},
			nil,
		),
}

registry2 := UserRegistry_Spec{
	Get: UserRegistry_Get_Expects(its.StringHavingPrefix("user-id:")).
		ThenEffect(func(userId string) (example.User, error) {
			return example.User{Id: "user-id:abcde", Name: "John Doe"}, nil
		}),
}

user, _ := UserRegistry_Build(t, registry).Get("user-id:abcdde")
its.EqEq(example.User{Id: "user-id:abcde", Name: "John Doe"}).Match(user).OrError(t)

user2, _ := UserRegistry_Build(t, registry2).Get("user-id:abcde")
its.EqEq(example.User{Id: "user-id:abcde", Name: "John Doe"}).Match(user2).OrError(t)
Output:

Example (Mock_failed_by_assertion)
registry := UserRegistry_Build(
	t,
	UserRegistry_Spec{
		Get: UserRegistry_Get_Expects(its.StringHavingPrefix("superuser:")).
			ThenReturn(
				example.User{Id: "user-id:abcde", Name: "John Doe"},
				nil,
			),
	},
)

registry.Get("user-id:abcdde")
Output:

✘ func UserRegistry_Get		--- @ ./mocker/mockkit/scenario_test.go:103
    ✘ userId :
        ✘ strings.HasPrefix(/* got */ "user-id:abcdde", /* want */ "superuser:")		--- @ ./mocker/mockkit/scenario_test.go:103
Example (Mock_failed_by_calling_not_mocked_method)
defer func() {
	recover()
}()

registry := UserRegistry_Build(
	t,
	UserRegistry_Spec{
		Get: UserRegistry_Get_Expects(its.StringHavingPrefix("superuser:")).
			ThenReturn(
				example.User{Id: "user-id:abcde", Name: "John Doe"},
				nil,
			),
	},
)

registry.Update(example.User{Id: "user-id:abcde", Name: "John Doe"})
Output:

✘ UserRegistry.Update is not mocked		--- @ ./mocker/mockkit/scenario_test.go:134
Example (Mock_passed)
registry := UserRegistry_Build(t, UserRegistry_Spec{
	Get: UserRegistry_Get_Expects(its.StringHavingPrefix("user-id:")).
		ThenReturn(
			example.User{Id: "user-id:abcde", Name: "John Doe"},
			nil,
		),
})

registry2 := UserRegistry_Build(t, UserRegistry_Spec{
	Get: UserRegistry_Get_Expects(its.StringHavingPrefix("user-id:")).
		ThenEffect(func(userId string) (example.User, error) {
			return example.User{Id: "user-id:abcde", Name: "John Doe"}, nil
		}),
})

user, _ := registry.Get("user-id:abcdde")
ItsUser(UserSpec{
	Id:   its.EqEq("user-id:abcde"),
	Name: its.EqEq("John Doe"),
}).
	Match(user).
	OrError(t)

user2, _ := registry2.Get("user-id:abcde")
its.EqEq(example.User{Id: "user-id:abcde", Name: "John Doe"}).Match(user2).OrError(t)
Output:

Example (Scenario_failed_by_plans_incompleted)
sc := mockkit.BeginScenario(t)
defer sc.End()

sess := mockkit.Next(
	sc,
	SessionStore_Expects(its.EqEq("fake-cookie")).
		ThenReturn("sample-user-id", true),
)

registry := UserRegistry_Spec{}
registry.Get = mockkit.Next(
	sc,
	UserRegistry_Get_Expects(its.EqEq("sample-user-id")).
		ThenReturn(
			example.User{
				Id:   "sample-user-id",
				Name: "John Doe",
			},
			nil,
		),
)

registry.Update = mockkit.Next(
	sc,
	UserRegistry_Update_Expects(
		ItsUser(
			UserSpec{
				Id:   its.EqEq("sample-user-id"),
				Name: its.EqEq("Richard Roe"),
			},
		),
	).
		ThenReturn(nil),
)

registry.Delete = mockkit.Next(
	sc,
	UserRegistry_Delete_Expects(its.Always[example.User]()).
		ThenReturn(nil),
)

testee := example.UpdateUser(
	sess.Fn(t),
	UserRegistry_Build(t, registry),
)

its.Nil[error]().Match(testee("fake-cookie", "Richard Roe")).OrError(t)
Output:

✘ // call order :
    ✘ []*mockkit.call{ ... (len: /* got */ 3, /* want */ 4; +0, -1)		--- @ ./mocker/mockkit/scenario_test.go:376
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:325).Equal(/* got */ ./mocker/mockkit/scenario_test.go:325 (invoked at ./mocker/internal/example/scenario.go:26))		--- @ ./mocker/mockkit/scenario_test.go:376
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:332).Equal(/* got */ ./mocker/mockkit/scenario_test.go:332 (invoked at ./mocker/internal/example/scenario.go:30))		--- @ ./mocker/mockkit/scenario_test.go:376
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:344).Equal(/* got */ ./mocker/mockkit/scenario_test.go:344 (invoked at ./mocker/internal/example/scenario.go:35))		--- @ ./mocker/mockkit/scenario_test.go:376
        ✘ - (/* want */ ./mocker/mockkit/scenario_test.go:357).Equal(/* got */ ??)		--- @ ./mocker/mockkit/scenario_test.go:376
Example (Scenario_failed_by_wrong_arg)
sc := mockkit.BeginScenario(t)
defer sc.End()

sess := mockkit.Next(
	sc,
	SessionStore_Expects(its.EqEq("fake-cookie")).
		ThenReturn("sample-user-id", true),
)

registry := UserRegistry_Spec{}
registry.Get = mockkit.Next(
	sc,
	UserRegistry_Get_Expects(its.EqEq("sample-user-id")).
		ThenReturn(
			example.User{
				Id:   "wrong-user-id", // WRONG!!!
				Name: "John Doe",
			},
			nil,
		),
)

registry.Update = mockkit.Next(
	sc,
	UserRegistry_Update_Expects(
		ItsUser(UserSpec{
			Id:   its.EqEq("sample-user-id"),
			Name: its.EqEq("Richard Roe"),
		}),
	).
		ThenReturn(nil),
)

testee := example.UpdateUser(
	sess.Fn(t),
	UserRegistry_Build(t, registry),
)

its.Nil[error]().Match(testee("fake-cookie", "Richard Roe")).OrError(t)
Output:

✘ func UserRegistry_Update		--- @ ./mocker/mockkit/scenario_test.go:248
    ✘ arg0 :
        ✘ type User:		--- @ ./mocker/mockkit/scenario_test.go:249
            ✘ .Id :		--- @ ./mocker/mockkit/scenario_test.go:249
                ✘ /* got */ wrong-user-id == /* want */ sample-user-id		--- @ ./mocker/mockkit/scenario_test.go:250
            ✔ .Name :		--- @ ./mocker/mockkit/scenario_test.go:249
                ✔ /* got */ Richard Roe == /* want */ Richard Roe		--- @ ./mocker/mockkit/scenario_test.go:251
Example (Scenario_failed_by_wrong_call_order)
sc := mockkit.BeginScenario(t)
defer sc.End()

registry := UserRegistry_Spec{}

registry.Get = mockkit.Next( // call #2
	sc,
	UserRegistry_Get_Expects(its.EqEq("sample-user-id")).
		ThenReturn(
			example.User{Id: "sample-user-id", Name: "John Doe"},
			nil,
		),
)

sess := mockkit.Next( // call #1
	sc,
	SessionStore_Expects(its.EqEq("fake-cookie")).
		ThenReturn("sample-user-id", true),
)

registry.Update = mockkit.Next( // call #3
	sc,
	UserRegistry_Update_Expects(
		ItsUser(UserSpec{
			Id:   its.EqEq("sample-user-id"),
			Name: its.EqEq("Richard Roe"),
		}),
	).
		ThenReturn(nil),
)

testee := example.UpdateUser(
	sess.Fn(t),
	UserRegistry_Build(t, registry),
)
err := testee("fake-cookie", "Richard Roe")

its.Nil[error]().Match(err).OrError(t)
Output:

✘ // call order :
    ✘ []*mockkit.call{ ... (len: /* got */ 3, /* want */ 3; +1, -1)		--- @ ./mocker/mockkit/scenario_test.go:319
        ✘ - (/* want */ ./mocker/mockkit/scenario_test.go:279).Equal(/* got */ ??)		--- @ ./mocker/mockkit/scenario_test.go:319
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:288).Equal(/* got */ ./mocker/mockkit/scenario_test.go:288 (invoked at ./mocker/internal/example/scenario.go:26))		--- @ ./mocker/mockkit/scenario_test.go:319
        ✘ + /* got */ ./mocker/mockkit/scenario_test.go:279 (invoked at ./mocker/internal/example/scenario.go:30)
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:294).Equal(/* got */ ./mocker/mockkit/scenario_test.go:294 (invoked at ./mocker/internal/example/scenario.go:35))		--- @ ./mocker/mockkit/scenario_test.go:319
Example (Scenario_passed)
// // assume them:
//
// type User struct {
// 	Id   string
// 	Name string
// }
//
// type UserRegistry interface {
// 	Get(userId string) (User, error)
// 	Update(User) error
// 	Delete(User) error
// }
//
// type SessionStore func(cookie string) (userId string, ok bool)
//
// // Let us test this web-like feature.
//
// func UpdateUser(
// 	sess SessionStore,
// 	registry UserRegistry,
// ) func(cookie string, newName string) error {
// 	return func(cookie, newName string) error {
// 		userId, ok := sess(cookie)
// 		if !ok {
// 			return errors.New("you are not logged in")
// 		}
// 		user, err := registry.Get(userId)
// 		if err != nil {
// 			return err
// 		}
// 		user.Name = newName
// 		return registry.Update(user)
// 	}
// }
//
// // SessionStore and UserRegistry will be injected to UpdateUser.
// // I want to test if these injected objects are handled propery.

sc := mockkit.BeginScenario(t)
defer sc.End()

sess := mockkit.Next( // add a function into scenario
	sc,
	SessionStore_Expects(
		its.EqEq("fake-cookie")).           // expectation for arguments
		ThenReturn("sample-user-id", true), // fixture for retrun valeus
)

registry := UserRegistry_Spec{}
registry.Get = mockkit.Next(
	sc,
	UserRegistry_Get_Expects(its.EqEq("sample-user-id")).
		ThenReturn(
			example.User{
				Id:   "sample-user-id",
				Name: "John Doe",
			},
			nil,
		),
)

registry.Update = mockkit.Next(
	sc,
	UserRegistry_Update_Expects(
		ItsUser(
			UserSpec{
				Id:   its.EqEq("sample-user-id"),
				Name: its.EqEq("Richard Roe"),
			},
		),
	).
		ThenReturn(nil),
)

testee := example.UpdateUser(
	sess.Fn(t),
	UserRegistry_Build(t, registry),
)

its.Nil[error]().Match(testee("fake-cookie", "Richard Roe")).OrError(t)
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FuncBehavior

type FuncBehavior[F any] interface {
	// Fn build a function from the FuncBehaviour.
	Fn(TestLike) F
}

FuncBehavior holds the expected behaveor of a function.

func Effect

func Effect[F any](func_ F) FuncBehavior[F]

Effect wraps a function as FuncBehavior

The FuncBehaviour returned from this does not perform any match. (always pass)

func Next

func Next[T any](s Scenario, funcBehaviour FuncBehavior[T]) FuncBehavior[T]

Next register a FuncBehavior to the scenario.

Args

- s Scenario: Testing Scenario

- funcBehaviour mocker.FuncBehaviour[T]: a behaviour to be called next.

type Scenario

type Scenario interface {

	// End checks if all functions are called in the expected order.
	//
	// If it isn't, it reports a test error.
	End()
	// contains filtered or unexported methods
}

Scenario describes the calling order of functions in the test target.

func BeginScenario

func BeginScenario(t TestLike) Scenario

BeginScenario create new empty scenatio.

Scenario tests that all planned functions are called in an order as planned.

You can plan functions with Next().

type SequentialBehavior

type SequentialBehavior[F any] interface {
	FuncBehavior[F]

	// Append registers FuncBehaviours to this SequentialBehaviour.
	Append(...FuncBehavior[F]) SequentialBehavior[F]
}

SequentialBehabiour is a container of FuncBehaviors

For each invocation of its Mock(), it calles Mock() of registered FuncBehaviors in a order.

func Sequential

func Sequential[F any](fb ...FuncBehavior[F]) SequentialBehavior[F]

Sequential builds SequentialBehavior.

All passed FuncBehaviours are registered to the returned SequentialBehavior as the order in parameters.

Example (Out_of_order)
sc := mockkit.BeginScenario(t)
defer sc.End()
defer func() {
	recover()
}()

seq := mockkit.Sequential(
	mockkit.Next(sc, mockkit.Effect(func() int { return 10 })),
	mockkit.Next(sc, mockkit.Effect(func() int { return 11 })),
)
inserted := mockkit.Next(sc, mockkit.Effect(func() int { return 99 })).Fn(t)
seq.Append(
	mockkit.Next(sc, mockkit.Effect(func() int { return 12 })),
	mockkit.Next(sc, mockkit.Effect(func() int { return 13 })),
)

testee := seq.Fn(t)

got := []int{
	testee(),
	testee(),
	testee(),
	inserted(),
	testee(),
}

its.ForItems(its.Slice, its.EqEq, []int{10, 11, 12, 99, 13}).Match(got).OrError(t)
Output:

✘ // call order :
    ✘ []*mockkit.call{ ... (len: /* got */ 5, /* want */ 5; +1, -1)		--- @ ./mocker/mockkit/scenario_test.go:472
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:442).Equal(/* got */ ./mocker/mockkit/scenario_test.go:442 (invoked at ./mocker/mockkit/scenario_test.go:454))		--- @ ./mocker/mockkit/scenario_test.go:472
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:443).Equal(/* got */ ./mocker/mockkit/scenario_test.go:443 (invoked at ./mocker/mockkit/scenario_test.go:455))		--- @ ./mocker/mockkit/scenario_test.go:472
        ✘ - (/* want */ ./mocker/mockkit/scenario_test.go:445).Equal(/* got */ ??)		--- @ ./mocker/mockkit/scenario_test.go:472
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:447).Equal(/* got */ ./mocker/mockkit/scenario_test.go:447 (invoked at ./mocker/mockkit/scenario_test.go:456))		--- @ ./mocker/mockkit/scenario_test.go:472
        ✘ + /* got */ ./mocker/mockkit/scenario_test.go:445 (invoked at ./mocker/mockkit/scenario_test.go:457)
        ✔ (/* want */ ./mocker/mockkit/scenario_test.go:448).Equal(/* got */ ./mocker/mockkit/scenario_test.go:448 (invoked at ./mocker/mockkit/scenario_test.go:458))		--- @ ./mocker/mockkit/scenario_test.go:472
Example (Too_much_invoke)
sc := mockkit.BeginScenario(t)
defer sc.End()
defer func() {
	recover()
}()

seq := mockkit.Sequential(
	mockkit.Next(sc, mockkit.Effect(func() int { return 10 })),
	mockkit.Next(sc, mockkit.Effect(func() int { return 11 })),
)
inserted := mockkit.Next(sc, mockkit.Effect(func() int { return 99 })).Fn(t)
seq.Append(
	mockkit.Next(sc, mockkit.Effect(func() int { return 12 })),
	mockkit.Next(sc, mockkit.Effect(func() int { return 13 })),
)

testee := seq.Fn(t)

got := []int{
	testee(), testee(), inserted(), testee(), testee(),
}

its.ForItems(its.Slice, its.EqEq, []int{10, 11, 99, 12, 13}).Match(got).OrError(t)

testee() // extra call!

fmt.Println("does not reach here")
Output:

✘ // invoke count :		--- @ ./mocker/mockkit/scenario_test.go:425
    ✘ /* want */ 4 >= /* got */ 5		--- @ ./mocker/mockkit/scenario_test.go:417

type TestLike

type TestLike interface {
	Error(...any)
	Fatal(...any)
}

TestLike is a type like *testing.T

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL