dpps0715 2017-04-14 09:14
浏览 40
已采纳

函数在golang中通过接口模拟

I am trying to write a unit test code form following code which has 3 level of function calling as below:

The main function calls function A() and then function A calls function B() and C() depending upon some condition and function B calls function E() and F(), whereas function C calls function G() and H() on some condition.
The above like the code I have developed, Here I want to mock function E() and F() for function B, and G() and H() for function C. Please suggest me how to do it using interface.

  • 写回答

1条回答 默认 最新

  • dsour68888 2017-04-14 09:32
    关注

    Abstract function type

    You can do it with dependency injection not using interfaces:

    import (
        "fmt"
        "math"
    )
    
    type a func(float64) float64
    
    func A(arg float64) float64 {
        return math.Pow(arg, 2)
    }
    
    func mock(arg float64) float64 {
        return math.Sqrt(arg)
    }
    
    func b(function a, arg float64) float64 {
        return function(arg)
    }
    
    func main() {
        fmt.Println(b(A, 2))
        fmt.Println(b(mock, 2))
    }
    

    Function is first class citizen in Go

    In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities.

    It means you can pass function as argument among other possibilities. And of course you can declare an abstract type based on function with concrete interface (Don't confuse with interface type)

    Interface approach

    You can make compositions using your functions

    import (
        "fmt"
        "math"
    )
    
    // Declare an interface type with dependencies
    type HGer interface {
        H(float64) float64
        G(float64) float64
    }
    
    // Declare a dependent type with embedded interface
    type Dependent struct {
        HGer
    }
    
    func (d *Dependent) B(arg float64) float64 {
        return d.H(arg) * d.G(arg)
    }
    
    // Implement the interface for an actual program
    type ImplHGer struct{}
    
    func (i *ImplHGer) H(arg float64) float64 {
        return math.Pow(arg, 2)
    }
    
    func (i *ImplHGer) G(arg float64) float64 {
        return math.Sqrt(arg)
    }
    
    // Implement the interface for mock of dependencies
    type MockHGer struct{}
    
    func (i *MockHGer) H(arg float64) float64 {
        return float64(0)
    }
    
    func (i *MockHGer) G(arg float64) float64 {
        return float64(0)
    }
    
    func main() {
        // Use real implementation
        a := Dependent{new(ImplHGer)}
        // Use the mock
        b := Dependent{new(MockHGer)}
        fmt.Println(a.B(8)) // 181.01933598375618
        fmt.Println(b.B(8)) // 0
    }
    

    Embedding

    Including an anonymous field in a struct is known as embedding. In this case the Discount type is embedded in the PremiumDiscount type. All the methods of Discount are instantly available on the PremiumDiscount type. Furthermore those same methods can be hidden

    It is possible to embed interface to struct to extend it's behavior or to be more specific - declare abstract dependency.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?