github.com/tencent/goom@v1.0.1/when_test.go (about)

     1  // Package mocker_test 对 mocker 包的测试
     2  // 当前文件实现了对 when.go 的单测
     3  package mocker_test
     4  
     5  import (
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/suite"
    10  	mocker "github.com/tencent/goom"
    11  	"github.com/tencent/goom/arg"
    12  )
    13  
    14  // TestUnitWhenTestSuite 测试入口
    15  func TestUnitWhenTestSuite(t *testing.T) {
    16  	suite.Run(t, new(WhenTestSuite))
    17  }
    18  
    19  // mockerTestSuite Builder 测试套件
    20  type WhenTestSuite struct {
    21  	suite.Suite
    22  }
    23  
    24  // simple 普通函数
    25  func simple(int) int {
    26  	return 0
    27  }
    28  
    29  // Arg 普通参数
    30  type Arg struct {
    31  	field1 string
    32  }
    33  
    34  // Result 普通返回结果
    35  type Result struct {
    36  	field1 int
    37  }
    38  
    39  // complex 复杂返回结果函数
    40  func complex(Arg) Result {
    41  	return Result{0}
    42  }
    43  
    44  // complex1 复杂带指针的返回结果函数
    45  func complex1(Arg) *Result {
    46  	return &Result{0}
    47  }
    48  
    49  // Struct for 结构体方法 When
    50  type Struct struct{}
    51  
    52  // Div 除法操作
    53  //
    54  //go:noinline
    55  func (s *Struct) Div(a int, b int) int {
    56  	return a / b
    57  }
    58  
    59  // Expand 展开数组
    60  //
    61  //go:noinline
    62  func (s *Struct) Expand(arg []int) (int, int) {
    63  	if len(arg) != 2 {
    64  		return 0, 0
    65  	}
    66  	return arg[0], arg[1]
    67  }
    68  
    69  // StructOuter 嵌套结构外层
    70  type StructOuter struct {
    71  }
    72  
    73  // Compute 中会调用 sub 运算
    74  func (s *StructOuter) Compute(a int, b int) int {
    75  	diver := new(Struct)
    76  	res := diver.Div(a, b)
    77  
    78  	return res
    79  }
    80  
    81  // TestWhen 测试简单参数匹配
    82  func (s *WhenTestSuite) TestWhen() {
    83  	s.Run("success", func() {
    84  		when := mocker.NewWhen(reflect.TypeOf(simple))
    85  		when.When(1).Return(2)
    86  
    87  		s.Equal(2, when.Eval(1)[0], "when result check")
    88  	})
    89  }
    90  
    91  // TestWhenAndReturn 多次返回不同的值
    92  func (s *WhenTestSuite) TestWhenAndReturn() {
    93  	s.Run("success", func() {
    94  		when := mocker.NewWhen(reflect.TypeOf(simple))
    95  		when.When(1).Return(2).AndReturn(3)
    96  
    97  		s.Equal(2, when.Eval(1)[0], "when result check")
    98  		s.Equal(3, when.Eval(1)[0], "when result check")
    99  		s.Equal(3, when.Eval(1)[0], "when result check")
   100  	})
   101  }
   102  
   103  // TestReturns 依次返回不同的值
   104  func (s *WhenTestSuite) TestReturns() {
   105  	s.Run("success", func() {
   106  		when := mocker.NewWhen(reflect.TypeOf(simple))
   107  		when.Returns(1, 2, 3)
   108  
   109  		s.Equal(1, when.Eval(1)[0], "when result check")
   110  		s.Equal(2, when.Eval(1)[0], "when result check")
   111  		s.Equal(3, when.Eval(1)[0], "when result check")
   112  
   113  		when.When(2).Returns(4, 5, 6)
   114  
   115  		s.Equal(4, when.Eval(2)[0], "when result check")
   116  		s.Equal(5, when.Eval(2)[0], "when result check")
   117  		s.Equal(6, when.Eval(2)[0], "when result check")
   118  
   119  		// 多参 Returns
   120  		struct1 := new(Struct)
   121  		m := mocker.Create()
   122  		m.Struct(struct1).Method("Expand").Returns(
   123  			[]interface{}{1, 1}, []interface{}{2, 2}, []interface{}{3, 3})
   124  
   125  		ret1, ret2 := struct1.Expand([]int{0, 0})
   126  		s.Equal(1, ret1, "method when check")
   127  		s.Equal(1, ret2, "method when check")
   128  
   129  		ret1, ret2 = struct1.Expand([]int{0, 0})
   130  		s.Equal(2, ret1, "method when check")
   131  		s.Equal(2, ret2, "method when check")
   132  
   133  		ret1, ret2 = struct1.Expand([]int{0, 0})
   134  		s.Equal(3, ret1, "method when check")
   135  		s.Equal(3, ret2, "method when check")
   136  
   137  		// 复杂返回结构
   138  		when = mocker.NewWhen(reflect.TypeOf(complex1))
   139  		when.Returns(&Result{}, nil)
   140  		s.Equal(&Result{}, when.Eval(Arg{})[0], "when result check")
   141  		s.Equal(nil, when.Eval(Arg{})[0], "when result check")
   142  	})
   143  }
   144  
   145  // TestWhenContains 任意一个配
   146  func (s *WhenTestSuite) TestWhenContains() {
   147  	s.Run("success", func() {
   148  		when := mocker.NewWhen(reflect.TypeOf(simple))
   149  		when.Return(-1).In(1, 2).Return(5)
   150  
   151  		s.Equal(5, when.Eval(1)[0], "when result check")
   152  		s.Equal(5, when.Eval(1)[0], "when result check")
   153  		s.Equal(-1, when.Eval(0)[0], "when result check")
   154  
   155  		when.Return(-1).When(arg.In(3, 4)).Return(6)
   156  
   157  		s.Equal(6, when.Eval(3)[0], "when result check")
   158  		s.Equal(6, when.Eval(4)[0], "when result check")
   159  	})
   160  }
   161  
   162  // TestMatches 测试批量设置条件
   163  func (s *WhenTestSuite) TestMatches() {
   164  	s.Run("success", func() {
   165  		when := mocker.NewWhen(reflect.TypeOf(simple))
   166  		when.Return(-1).Matches(
   167  			arg.Pair{Args: 1, Return: 5},
   168  			arg.Pair{Args: 2, Return: 5},
   169  			arg.Pair{Args: 3, Return: 6})
   170  
   171  		s.Equal(5, when.Eval(1)[0], "when result check")
   172  		s.Equal(5, when.Eval(2)[0], "when result check")
   173  		s.Equal(6, when.Eval(3)[0], "when result check")
   174  
   175  		when.Matches(arg.Pair{Args: arg.Any(), Return: 100})
   176  		s.Equal(100, when.Eval(4)[0], "when result check")
   177  	})
   178  }
   179  
   180  // TestNil 测试复杂参数
   181  func (s *WhenTestSuite) TestComplex() {
   182  	s.Run("success", func() {
   183  		when := mocker.NewWhen(reflect.TypeOf(complex))
   184  		when.Return(Result{}).When(Arg{field1: "ok"}).Return(Result{0}).
   185  			When(Arg{field1: "not ok"}).Return(Result{-1})
   186  
   187  		s.Equal(Result{0}, when.Eval(Arg{field1: "ok"})[0], "when result check")
   188  		s.Equal(Result{-1}, when.Eval(Arg{field1: "not ok"})[0], "when result check")
   189  		s.Equal(Result{}, when.Eval(Arg{field1: "other"})[0], "when result check")
   190  	})
   191  }
   192  
   193  // TestNil 测试空参数
   194  func (s *WhenTestSuite) TestNil() {
   195  	s.Run("success", func() {
   196  		when := mocker.NewWhen(reflect.TypeOf(complex1))
   197  		when.Return(nil)
   198  
   199  		s.Equal(nil, when.Eval(Arg{})[0], "when return nil check")
   200  	})
   201  }
   202  
   203  // TestMethodWhen 方法参数条件匹配
   204  func (s *WhenTestSuite) TestMethodWhen() {
   205  	s.Run("success", func() {
   206  		structOuter := new(StructOuter)
   207  		struct1 := new(Struct)
   208  		m := mocker.Create()
   209  
   210  		// 直接 mock 方法的返回值
   211  		m.Struct(struct1).Method("Div").Return(100)
   212  		s.Equal(100, structOuter.Compute(2, 1), "method when check")
   213  
   214  		m.Reset()
   215  		m.Struct(struct1).Method("Div").Return(50)
   216  		s.Equal(50, structOuter.Compute(2, 1), "method when check")
   217  
   218  		m.Struct(struct1).Method("Div").When(3, 4).Return(100)
   219  		m.Struct(struct1).Method("Div").When(4, 4).Return(200)
   220  		s.Equal(100, structOuter.Compute(3, 4), "method when check")
   221  		s.Equal(200, structOuter.Compute(4, 4), "method when check")
   222  
   223  		// mock 方法的替换方法
   224  		m.Struct(struct1).Method("Div").Apply(func(_ *Struct, a int, b int) int {
   225  			return a/b + 1
   226  		})
   227  		s.Equal(3, structOuter.Compute(2, 1), "method when check")
   228  	})
   229  }
   230  
   231  // TestMethodAny 方法参数 Any 条件匹配
   232  func (s *WhenTestSuite) TestMethodAny() {
   233  	s.Run("success", func() {
   234  		structOuter := new(StructOuter)
   235  		struct1 := new(Struct)
   236  		m := mocker.Create()
   237  
   238  		m.Struct(struct1).Method("Div").When(3, arg.Any()).Return(100)
   239  		s.Equal(100, structOuter.Compute(3, 1), "method when check")
   240  		s.Equal(100, structOuter.Compute(3, 2), "method when check")
   241  		s.Equal(100, structOuter.Compute(3, -1), "method when check")
   242  	})
   243  }
   244  
   245  // TestMethodMultiIn 方法参数 Any 条件匹配
   246  func (s *WhenTestSuite) TestMethodMultiIn() {
   247  	s.Run("success", func() {
   248  		structOuter := new(StructOuter)
   249  		struct1 := new(Struct)
   250  		m := mocker.Create()
   251  
   252  		when := m.Struct(struct1).Method("Div").Return(-1).When(arg.In(3, 4), arg.Any()).Return(100)
   253  		s.Equal(100, structOuter.Compute(3, 1), "method when check")
   254  		s.Equal(100, structOuter.Compute(3, 2), "method when check")
   255  		s.Equal(100, structOuter.Compute(4, 3), "method when check")
   256  		s.Equal(100, structOuter.Compute(3, -1), "method when check")
   257  
   258  		when.In([]interface{}{5, arg.Any()}).Return(101)
   259  		s.Equal(101, structOuter.Compute(5, 1), "method when check")
   260  		s.Equal(101, structOuter.Compute(5, 2), "method when check")
   261  		s.Equal(101, structOuter.Compute(5, -1), "method when check")
   262  
   263  		when.Matches(
   264  			arg.Pair{Args: []interface{}{6, arg.Any()}, Return: []interface{}{101}},
   265  			arg.Pair{Args: []interface{}{7, arg.Any()}, Return: []interface{}{102}},
   266  		)
   267  		s.Equal(101, structOuter.Compute(6, -1), "method when check")
   268  		s.Equal(102, structOuter.Compute(7, -1), "method when check")
   269  	})
   270  }