github.com/bytedance/mockey@v1.2.10/convey.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  	"reflect"
    21  
    22  	"github.com/bytedance/mockey/internal/tool"
    23  	"github.com/smartystreets/goconvey/convey"
    24  )
    25  
    26  var gMocker = make([]map[uintptr]mockerInstance, 0)
    27  
    28  func init() {
    29  	gMocker = append(gMocker, make(map[uintptr]mockerInstance))
    30  }
    31  
    32  func PatchConvey(items ...interface{}) {
    33  	for i, item := range items {
    34  		if reflect.TypeOf(item).Kind() == reflect.Func {
    35  			items[i] = reflect.MakeFunc(reflect.TypeOf(item), func(args []reflect.Value) []reflect.Value {
    36  				gMocker = append(gMocker, make(map[uintptr]mockerInstance))
    37  				defer func() {
    38  					for _, mocker := range gMocker[len(gMocker)-1] {
    39  						mocker.unPatch()
    40  					}
    41  					gMocker = gMocker[:len(gMocker)-1]
    42  				}()
    43  				return tool.ReflectCall(reflect.ValueOf(item), args)
    44  			}).Interface()
    45  		}
    46  	}
    47  
    48  	convey.Convey(items...)
    49  }
    50  
    51  func addToGlobal(mocker mockerInstance) {
    52  	tool.DebugPrintf("%v added\n", mocker.key())
    53  	last, ok := gMocker[len(gMocker)-1][mocker.key()]
    54  	if ok {
    55  		tool.Assert(!ok, "re-mock %v, previous mock at: %v", mocker.name(), last.caller())
    56  	}
    57  	gMocker[len(gMocker)-1][mocker.key()] = mocker
    58  }
    59  
    60  func removeFromGlobal(mocker mockerInstance) {
    61  	tool.DebugPrintf("%v removed\n", mocker.key())
    62  	delete(gMocker[len(gMocker)-1], mocker.key())
    63  }
    64  
    65  // Unpatch all mocks in current 'PatchConvey' context
    66  //
    67  // If the caller is out of 'PatchConvey', it will unpatch all mocks
    68  //
    69  // For example:
    70  //
    71  //		Test1(t) {
    72  //			Mock(a).Build()
    73  //		 	Mock(b).Build()
    74  //
    75  //			// a and b will be unpatched
    76  //			UnpatchAll()
    77  //		}
    78  //		})
    79  //
    80  //		Test2(t) {
    81  //		Mock(a).Build()
    82  //		PatchConvey(t,func(){
    83  //		 	Mock(b).Build()
    84  //
    85  //			// only b will be unpatched
    86  //			UnpatchAll()
    87  //		}
    88  //	})
    89  func UnPatchAll() {
    90  	for _, mocker := range gMocker[len(gMocker)-1] {
    91  		mocker.unPatch()
    92  	}
    93  }