-1
package main

import (
    "net/http"
    "sync"
    "time"
)

type SessionInterface1 interface {
    doLoginAndReadDestinations1() bool
}

type Session1 struct {
    sessionCookie string
    mux           sync.Mutex
    sessionTime   time.Time
    targetAddress string
    currentJwt    string
    transport     *http.Transport
}

var currentSession1 Session1

func main() {

    currentSession1.verifyLogin1()

}

func (s *Session1) doLoginAndReadDestinations1() bool {
    ..logic...
    ... for example return true

}

func callDest1(si SessionInterface1) bool {
    return si.doLoginAndReadDestinations1()
}

func (s *Session1) verifyLogin1() bool {
    return callDest1(s)
}

I want to create unit test and to mock doLoginAndReadDestinations1 I tried to create interface for this method and I create test

func test1(t *testing.T) {
    type args struct {
    }
    tests := []struct {
        name string
        args args
        want bool
    }{{
        name: "test",
        args: args{},
        want: false,
    }}
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            var s1 *Session1
            count := 10
            s1 = &Session1{"", sync.Mutex{}, time.Now(), "", "", nil}

            var got1 = s1.verifyLogin()

            if got1 != tt.want {
                t.Errorf("getJwt() = %v, want %v", got, tt.want)
            }

        })
    }
}

I didn't know how I can change the logic of function doLoginAndReadDestinations1 in the test and to change the logic in the first main

user1365697
  • 5,819
  • 15
  • 60
  • 96
  • 1
    It looks like your posted code is the mock, so it's not really clear what your question is about it. – Adrian Oct 31 '18 at 18:45
  • I want to do mock for this function doLoginAndReadDestinations1 in the test How I can do it ? – user1365697 Oct 31 '18 at 18:46
  • 1
    Is the one posted not a mock? The one that's just `return true`? – Adrian Oct 31 '18 at 18:52
  • it is just an example the idea that there is any logic there , I will update it – user1365697 Oct 31 '18 at 18:56
  • The verifyLogin on Session is called to doLoginAndReadDestinations1 that have complex logic with HTTP call and more logic and I in my test I just want that this method will return true, – user1365697 Oct 31 '18 at 18:59

2 Answers2

2

In your unit test, you're only calling methods on Session1, not on something that calls Session1's methods; so there isn't anything to mock. When using mocking for tests, you don't mock methods, you mock types, when those types are dependencies of the type under test. For example, if you have a type Foo which depends on (calls methods of) a type Bar, and you want to test Foo in isolation, you would create a mock of type Bar, and in your tests for Foo, you'd give it your BarMock instead of Bar. In your real code, you'd give it the real Bar. There is no way to mock a single method of a type.

You might find this StackOverflow question and its extensive answers helpful.

Adrian
  • 42,911
  • 6
  • 107
  • 99
  • The idea that Call to method verifyLogin that call to callDest1 that it is interface of doLoginAndReadDestinations1 I want to mock this function and not to call to the real one. do I need to change the real code ? if yes how ? – user1365697 Oct 31 '18 at 19:08
  • My problem that I want to write test that will not do the logic of doLoginAndReadDestinations1 in the verifyLogin test – user1365697 Oct 31 '18 at 19:09
  • Again, *you cannot mock a method, you can only mock a type*. If you want to mock only that function, you need to move it to a new type, create an interface, add a field to the original type, and fill that new field with your mock implementation in your tests and the real implementation in your production code. – Adrian Oct 31 '18 at 19:30
  • sorry I am not expert in this could you give me an example How I need to do it ? – user1365697 Oct 31 '18 at 19:37
  • could we have a short chat ? – user1365697 Oct 31 '18 at 19:38
  • type SessionInterface1 interface { doLoginAndReadDestinations1() bool } is a new type with interface – user1365697 Oct 31 '18 at 20:10
2

You will need to abstract everything you want to mock. Instead of resolving dependency as a concrete implementation, use an interface. Then you will be able to create a mock which will implement this interface.

Generally, I would suggest you stretchr/testify for testing. It has methods for :

  1. assert
  2. require
  3. mock
  4. suite

This library will help you structuring test, writing tests and remove your boilerplate code. It has mocking mechanisms inside. Read about mocking interfaces at testify mock section

Maxian Nicu
  • 2,166
  • 3
  • 17
  • 31