Repository: stretchr/testify (go)

Issue:
(syntax sugar) Implement an `InOrder` func for mocks
<!-- If this is a question, consider using the discussion section of this repo -->
<!-- Here: https://github.com/stretchr/testify/discussions/new?category=q-a -->

## Description
<!-- A clear and concise description of what feature you are proposing -->
Since [gomock](https://github.com/golang/mock) has been archived, I am switching to testify's mock pkg.

One extremely neat feature that gomock had is the `InOrder` func:
https://pkg.go.dev/github.com/golang/mock/gomock#InOrder

Which allowed to very easily enforce expectation order by going from:
```go
someMock.EXPECT().ValidateArgs(gomock.Any(), 1).Return(nil),
someMock.EXPECT().ValidateArgs(gomock.Any(), 2).Return(nil)
```
to
```go
gomock.InOrder(
    someMock.EXPECT().ValidateArgs(gomock.Any(), 1).Return(nil),
    someMock.EXPECT().ValidateArgs(gomock.Any(), 2).Return(nil)
)
```

As opposed to the current API implemented in testify which is more cumbersome and less intuitive with the need to declare vars and pass them inside the last chained method.
https://github.com/stretchr/testify/issues/741
https://github.com/stretchr/testify/pull/1106

```go
call1 := mockThing.On("Init").Return(nil)
call2 := mockThing.On("Do").Return(nil).NotBefore(call1)
mockThing.On("Close").Return(nil).NotBefore(call1, call2)
```

Or I guess do some kind of nesting which reverse the chronological order of events and creates nesting.
```go
mockThing.On("Close").Return(nil).NotBefore(
    mockThing.On("Do").Return(nil).NotBefore(
        mockThing.On("Init").Return(nil).NotBefore(
            ... nesting
)
```

Ideally could be turned into:

```go
mock.InOrder(
    mockThing.On("Init").Return(nil),
    mockThing.On("Do").Return(nil),
    mockThing.On("Close").Return(nil)
)
```

## Proposed solution
<!-- Optionally a suggested implementation -->

I didn't looked into the codebase yet to know if that's easily feasible. 
But my gut feeling says it could be trivial to chain the `NotBefore` inside the `mock.InOrder` variadic function.
This issue is mostly to gather feedback.

## Use case
<!-- What is the motivation? What workarounds have you used? -->

More intuitive API.

Pull request:
mock: in order mock calls
## Summary
<!-- High-level, one sentence summary of what this PR accomplishes -->

Add helper method to declare the order of the mock calls.

## Changes
<!-- * Description of change 1 -->
<!-- * Description of change 2 -->
<!-- ... -->

* add `InOrder(calls ...*Call)` helper method to declare the order of mock calls by calling `NotBefore()`


## Motivation
<!-- Why were the changes necessary. -->

This is probably the only feature I miss from `gomock.InOrder()`, it is more intuitive and cleaner to declare the order of the mock calls. Probably most cases can be satisfied with this method.

<!-- ## Example usage (if applicable) -->
```
InOrder(
	mockedService1.On("TheExampleMethod", 1, 2, 3).Return(4, nil),
	mockedService2.On("TheExampleMethod2", true).Return(),
	mockedService3.On("TheExampleMethod3", "abc", 3).Return(false, nil),
)

```
## Related issues
Closes #1639 


Patch:
diff --git a/mock/mock.go b/mock/mock.go
index 8f090fd..41257fb 100644
--- a/mock/mock.go
+++ b/mock/mock.go
@@ -273,6 +273,20 @@ func (c *Call) NotBefore(calls ...*Call) *Call {
 	return c
 }
 
+// InOrder defines the order in which the calls should be made
+//
+//	For example:
+//
+//	InOrder(
+//		Mock.On("init").Return(nil),
+//		Mock.On("Do").Return(nil),
+//	)
+func InOrder(calls ...*Call) {
+	for i := 1; i < len(calls); i++ {
+		calls[i].NotBefore(calls[i-1])
+	}
+}
+
 // Mock is the workhorse used to track activity on another object.
 // For an example of its usage, refer to the "Example Usage" section at the top
 // of this document.


Test patch:
diff --git a/mock/mock_test.go b/mock/mock_test.go
index 95159d8..d286867 100644
--- a/mock/mock_test.go
+++ b/mock/mock_test.go
@@ -937,6 +937,26 @@ func Test_Mock_Return_NotBefore_In_Order(t *testing.T) {
 	})
 }
 
+func Test_Mock_Return_InOrder_Uses_NotBefore(t *testing.T) {
+	var mockedService = new(TestExampleImplementation)
+
+	InOrder(
+		mockedService.
+			On("TheExampleMethod", 1, 2, 3).
+			Return(4, nil),
+		mockedService.
+			On("TheExampleMethod2", true).
+			Return(),
+	)
+
+	require.NotPanics(t, func() {
+		mockedService.TheExampleMethod(1, 2, 3)
+	})
+	require.NotPanics(t, func() {
+		mockedService.TheExampleMethod2(true)
+	})
+}
+
 func Test_Mock_Return_NotBefore_Out_Of_Order(t *testing.T) {
 	var mockedService = new(TestExampleImplementation)
 
@@ -967,6 +987,35 @@ TheExampleMethod(int,int,int)
 	})
 }
 
+func Test_Mock_Return_InOrder_Uses_NotBefore_Out_Of_Order(t *testing.T) {
+	var mockedService = new(TestExampleImplementation)
+
+	InOrder(
+		mockedService.
+			On("TheExampleMethod", 1, 2, 3).
+			Return(4, nil).Twice(),
+		mockedService.
+			On("TheExampleMethod2", true).
+			Return(),
+	)
+
+	expectedPanicString := `mock: Unexpected Method Call
+-----------------------------
+
+TheExampleMethod2(bool)
+		0: true
+
+Must not be called before:
+
+TheExampleMethod(int,int,int)
+		0: 1
+		1: 2
+		2: 3`
+	require.PanicsWithValue(t, expectedPanicString, func() {
+		mockedService.TheExampleMethod2(true)
+	})
+}
+
 func Test_Mock_Return_NotBefore_Not_Enough_Times(t *testing.T) {
 	var mockedService = new(TestExampleImplementation)
 
@@ -1022,6 +1071,7 @@ func Test_Mock_Return_NotBefore_Different_Mock_In_Order(t *testing.T) {
 		mockedService2.TheExampleMethod2(true)
 	})
 }
+
 func Test_Mock_Return_NotBefore_Different_Mock_Out_Of_Order(t *testing.T) {
 	var (
 		mockedService1 = new(TestExampleImplementation)