github.com/bytedance/mockey@v1.2.10/mock_condition_test.go (about)

     1  /*
     2   * Copyright 2022 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package mockey
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/smartystreets/goconvey/convey"
    24  )
    25  
    26  type multiConditionStruct struct {
    27  	Field string
    28  }
    29  
    30  func (m *multiConditionStruct) Foo(in int) string {
    31  	return m.Field
    32  }
    33  
    34  func TestMultiCondition(t *testing.T) {
    35  	PatchConvey("multi condition", t, func() {
    36  		PatchConvey("function", func() {
    37  			fn := func(i int) string {
    38  				fmt.Println() // to avoid an old unresolved bug,see https://github.com/bytedance/mockey/issues/24
    39  				return "fn:not here"
    40  			}
    41  
    42  			builder := Mock(fn)
    43  			builder.When(func(i int) bool { return i > 0 && i < 3 }).To(func(i int) string {
    44  				if i == 1 {
    45  					return "to:1"
    46  				}
    47  				if i == 2 {
    48  					return "to:2"
    49  				}
    50  				panic("to:not here")
    51  			})
    52  			builder.Return("return:3").When(func(i int) bool { return i == 3 })
    53  
    54  			PatchConvey("normal", func() {
    55  				builder.Build()
    56  				convey.So(fn(0), convey.ShouldEqual, "fn:not here")
    57  				convey.So(fn(1), convey.ShouldEqual, "to:1")
    58  				convey.So(fn(2), convey.ShouldEqual, "to:2")
    59  				convey.So(fn(3), convey.ShouldEqual, "return:3")
    60  				convey.So(fn(4), convey.ShouldEqual, "fn:not here")
    61  			})
    62  
    63  			PatchConvey("missing when in last case", func() {
    64  				builder.To(func(i int) string { return "to:default" }).Build()
    65  				convey.So(fn(0), convey.ShouldEqual, "to:default")
    66  				convey.So(fn(1), convey.ShouldEqual, "to:1")
    67  				convey.So(fn(2), convey.ShouldEqual, "to:2")
    68  				convey.So(fn(3), convey.ShouldEqual, "return:3")
    69  				convey.So(fn(4), convey.ShouldEqual, "to:default")
    70  			})
    71  
    72  			PatchConvey("missing to/return in last case", func() {
    73  				builder.When(func(i int) bool { return i == 4 }).Build()
    74  				convey.So(fn(0), convey.ShouldEqual, "fn:not here")
    75  				convey.So(fn(1), convey.ShouldEqual, "to:1")
    76  				convey.So(fn(2), convey.ShouldEqual, "to:2")
    77  				convey.So(fn(3), convey.ShouldEqual, "return:3")
    78  				convey.So(fn(4), convey.ShouldEqual, "fn:not here")
    79  			})
    80  
    81  			PatchConvey("re-mock when not allowed in multi-condition", func() {
    82  				mocker := builder.Build()
    83  				convey.So(func() { mocker.When(func(i int) bool { return true }) }, convey.ShouldPanic)
    84  			})
    85  
    86  			PatchConvey("re-mock to not allowed in multi-condition", func() {
    87  				mocker := builder.Build()
    88  				convey.So(func() { mocker.To(func(i int) string { return "to" }) }, convey.ShouldPanic)
    89  			})
    90  
    91  			PatchConvey("continuous when/to/return not allowed in multi-condition", func() {
    92  				anyWhen := func(i int) bool { return true }
    93  				anyTo := func(i int) string { return "" }
    94  				anyReturn := ""
    95  				PatchConvey("when-when", func() {
    96  					convey.So(func() { builder.When(anyWhen).When(anyWhen) }, convey.ShouldPanic)
    97  				})
    98  				PatchConvey("to", func() {
    99  					builder.To(anyTo)
   100  					PatchConvey("to-to", func() {
   101  						convey.So(func() { builder.To(anyTo) }, convey.ShouldPanic)
   102  					})
   103  					PatchConvey("to-return", func() {
   104  						convey.So(func() { builder.Return(anyReturn) }, convey.ShouldPanic)
   105  					})
   106  				})
   107  				PatchConvey("return", func() {
   108  					builder.Return(anyReturn)
   109  					PatchConvey("return-to", func() {
   110  						convey.So(func() { builder.To(anyTo) }, convey.ShouldPanic)
   111  					})
   112  					PatchConvey("return-return", func() {
   113  						convey.So(func() { builder.Return(anyReturn) }, convey.ShouldPanic)
   114  					})
   115  				})
   116  			})
   117  		})
   118  
   119  		PatchConvey("struct", func() {
   120  			PatchConvey("origin with receiver", func() {
   121  				builder := Mock(GetMethod(&multiConditionStruct{}, "Foo"))
   122  				var origin func(self *multiConditionStruct, i int) string
   123  				builder.Origin(&origin)
   124  				builder.When(func(in int) bool { return in > 0 && in < 3 }).To(func(self *multiConditionStruct, i int) string {
   125  					if i == 1 {
   126  						return "to:1"
   127  					}
   128  					if i == 2 {
   129  						return "to:origin:" + origin(self, i)
   130  					}
   131  					panic("to:not here")
   132  				})
   133  				builder.Return("return:3").When(func(i int) bool { return i == 3 })
   134  				builder.Build()
   135  				obj := &multiConditionStruct{Field: "fn:not here"}
   136  				convey.So(obj.Foo(0), convey.ShouldEqual, "fn:not here")
   137  				convey.So(obj.Foo(1), convey.ShouldEqual, "to:1")
   138  				convey.So(obj.Foo(2), convey.ShouldEqual, "to:origin:fn:not here")
   139  				convey.So(obj.Foo(3), convey.ShouldEqual, "return:3")
   140  				convey.So(obj.Foo(4), convey.ShouldEqual, "fn:not here")
   141  			})
   142  
   143  			builder := Mock(GetMethod(&multiConditionStruct{}, "Foo"))
   144  			var origin func(i int) string
   145  			builder.Origin(&origin)
   146  			builder.When(func(in int) bool { return in > 0 && in < 3 }).To(func(i int) string {
   147  				if i == 1 {
   148  					return "to:1"
   149  				}
   150  				if i == 2 {
   151  					return "to:origin:" + origin(i)
   152  				}
   153  				panic("to:not here")
   154  			})
   155  			builder.Return("return:3").When(func(i int) bool { return i == 3 })
   156  
   157  			PatchConvey("normal", func() {
   158  				builder.Build()
   159  				obj := &multiConditionStruct{Field: "fn:not here"}
   160  				convey.So(obj.Foo(0), convey.ShouldEqual, "fn:not here")
   161  				convey.So(obj.Foo(1), convey.ShouldEqual, "to:1")
   162  				convey.So(obj.Foo(2), convey.ShouldEqual, "to:origin:fn:not here")
   163  				convey.So(obj.Foo(3), convey.ShouldEqual, "return:3")
   164  				convey.So(obj.Foo(4), convey.ShouldEqual, "fn:not here")
   165  			})
   166  			PatchConvey("missing when in last case", func() {
   167  				builder.To(func(i int) string { return "to:default" })
   168  				builder.Build()
   169  				obj := &multiConditionStruct{Field: "fn:not here"}
   170  				convey.So(obj.Foo(0), convey.ShouldEqual, "to:default")
   171  				convey.So(obj.Foo(1), convey.ShouldEqual, "to:1")
   172  				convey.So(obj.Foo(2), convey.ShouldEqual, "to:origin:fn:not here")
   173  				convey.So(obj.Foo(3), convey.ShouldEqual, "return:3")
   174  				convey.So(obj.Foo(4), convey.ShouldEqual, "to:default")
   175  			})
   176  			PatchConvey("missing to/return in last case", func() {
   177  				builder.When(func(i int) bool { return i == 4 })
   178  				builder.Build()
   179  				obj := &multiConditionStruct{Field: "fn:not here"}
   180  				convey.So(obj.Foo(0), convey.ShouldEqual, "fn:not here")
   181  				convey.So(obj.Foo(1), convey.ShouldEqual, "to:1")
   182  				convey.So(obj.Foo(2), convey.ShouldEqual, "to:origin:fn:not here")
   183  				convey.So(obj.Foo(3), convey.ShouldEqual, "return:3")
   184  				convey.So(obj.Foo(4), convey.ShouldEqual, "fn:not here")
   185  			})
   186  
   187  			PatchConvey("re-mock when not allowed in multi-condition", func() {
   188  				mocker := builder.Build()
   189  				convey.So(func() { mocker.When(func(i int) bool { return true }) }, convey.ShouldPanic)
   190  			})
   191  
   192  			PatchConvey("re-mock to not allowed in multi-condition", func() {
   193  				mocker := builder.Build()
   194  				convey.So(func() { mocker.To(func(i int) string { return "to" }) }, convey.ShouldPanic)
   195  			})
   196  
   197  			PatchConvey("re-mock return not allowed in multi-condition", func() {
   198  				mocker := builder.Build()
   199  				convey.So(func() { mocker.Return("to") }, convey.ShouldPanic)
   200  			})
   201  
   202  			PatchConvey("continuous when/to/return not allowed in multi-condition", func() {
   203  				anyWhen := func(i int) bool { return true }
   204  				anyTo := func(i int) string { return "" }
   205  				anyReturn := ""
   206  				PatchConvey("when-when", func() {
   207  					convey.So(func() { builder.When(anyWhen).When(anyWhen) }, convey.ShouldPanic)
   208  				})
   209  				PatchConvey("to", func() {
   210  					builder.To(anyTo)
   211  					PatchConvey("to-to", func() {
   212  						convey.So(func() { builder.To(anyTo) }, convey.ShouldPanic)
   213  					})
   214  					PatchConvey("to-return", func() {
   215  						convey.So(func() { builder.Return(anyReturn) }, convey.ShouldPanic)
   216  					})
   217  				})
   218  				PatchConvey("return", func() {
   219  					builder.Return(anyReturn)
   220  					PatchConvey("return-to", func() {
   221  						convey.So(func() { builder.To(anyTo) }, convey.ShouldPanic)
   222  					})
   223  					PatchConvey("return-return", func() {
   224  						convey.So(func() { builder.Return(anyReturn) }, convey.ShouldPanic)
   225  					})
   226  				})
   227  			})
   228  		})
   229  	})
   230  }