{
  "slug": "How-write-a-Unit-test--Integration-test--and-Performance-test-for-the-Golang-language--a25ccef115f4",
  "title": "How write a Unit test, Integration test, and Performance test for the Golang language?",
  "subtitle": "Explain way of testing golang application.",
  "excerpt": "Explain way of testing golang application.",
  "date": "2023-03-01",
  "tags": [
    "Star",
    "My Experience",
    "Go",
    "Performance",
    "Testing",
    "Machine Learning"
  ],
  "readingTime": "14 min",
  "url": "https://medium.com/@mobinshaterian/how-write-a-unit-test-integration-test-and-performance-test-for-the-golang-language-a25ccef115f4",
  "hero": "https://cdn-images-1.medium.com/max/800/1*I2NRnfrsWl_Pm45_w6NWkw.png",
  "content": [
    {
      "type": "heading",
      "level": 2,
      "text": "How do you write Unit, Integration, and Performance tests for the Golang language?"
    },
    {
      "type": "paragraph",
      "html": "Key Points on Testing in Go:"
    },
    {
      "type": "paragraph",
      "html": "1. Types of Tests:<br> — Unit tests: Test individual functions/components in isolation<br> — Integration tests: Test interactions between components, often using real databases/services<br> — Performance tests: Evaluate system performance under load<br> — End-to-end tests: Test full system functionality"
    },
    {
      "type": "paragraph",
      "html": "2. Unit Testing Best Practices:<br> — Aim for 70% code coverage&nbsp;<br> — Focus on testing business logic in the service layer<br> — Use mocks for external dependencies (databases, APIs, etc.)<br> — Utilize table-driven tests for multiple test cases<br> — Use testify package for assertions and mocks"
    },
    {
      "type": "paragraph",
      "html": "3. Writing Mocks:<br> — Use mockery tool to auto-generate mocks from interfaces<br> — Leverage go mock for argument matching and expectations<br> — Create mocks for databases, caches, gRPC clients, etc."
    },
    {
      "type": "paragraph",
      "html": "4. Integration Testing:<br> — Use Docker to set up test environments with real databases/services<br> — Utilize Liquibase for database migrations and seeding test data<br> — Test interactions between microservices"
    },
    {
      "type": "paragraph",
      "html": "5. Performance Testing:<br> — Use tools like Locust.io to simulate user load<br> — Evaluate response times and system behavior under concurrent load"
    },
    {
      "type": "paragraph",
      "html": "6. Test Output and Reporting:<br> — Use JUnit XML format for CI/CD integration<br> — Generate code coverage reports with Cobertura"
    },
    {
      "type": "paragraph",
      "html": "7. Additional Testing Approaches:<br> — Behavior Driven Development (BDD)&nbsp;<br> — Security scanning with tools like Trivy<br> — Contract testing for microservices with Pact"
    },
    {
      "type": "paragraph",
      "html": "8. Go-Specific Testing Features:<br> — TestMain for custom test setup/teardown<br> — Use of testing.T struct for test state and assertions<br> — Built-in benchmarking capabilities"
    },
    {
      "type": "paragraph",
      "html": "Key Recommendations:<br>- Start with unit tests for core business logic<br>- Gradually add integration and performance tests<br>- Leverage mocking to isolate components under test<br>- Automate tests in the CI/CD pipeline<br>- Monitor test coverage and expand over time<br>- Use specialized tools for security and load testing"
    },
    {
      "type": "paragraph",
      "html": "Overall, Go provides a robust testing framework that can be extended with community tools to enable comprehensive testing of applications. A multi-layered testing approach combining unit, integration, and performance tests is recommended for building reliable Go applications."
    },
    {
      "type": "paragraph",
      "html": "Special thanks to <a href=\"https://medium.com/u/44a7f70b3770\" target=\"_blank\" rel=\"noreferrer noopener\">Mohsen Mottaghi</a>."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*I2NRnfrsWl_Pm45_w6NWkw.png",
      "alt": "https://www.headspin.io/blog/the-testing-pyramid-simplified-for-one-and-all",
      "caption": "https://www.headspin.io/blog/the-testing-pyramid-simplified-for-one-and-all",
      "width": 869,
      "height": 674
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*5Hz3xd2N4A5-VyOzAFWpFQ.png",
      "alt": "https://medium.com/@nathankpeck/microservice-testing-introduction-347d2f74095e",
      "caption": "https://medium.com/@nathankpeck/microservice-testing-introduction-347d2f74095e",
      "width": 798,
      "height": 412
    },
    {
      "type": "paragraph",
      "html": "In all applications, the only way we can be sure every function works correctly is by writing the test. Special financial applications need a test and 70 percent of the covering code. One of the reasons we need to test is if some new development will add to our company and change financial calculations, how can we ensure that everything will work correctly?"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Is it necessary to write a test, or is it a waste of time?"
    },
    {
      "type": "paragraph",
      "html": "Developer: “When is the project expected to be completed?”&nbsp;<br>Business Owner: “Yesterday”"
    },
    {
      "type": "paragraph",
      "html": "The powerful advantage of writing the test is maintenance and being ready for critical situations before they happen. If the company doesn’t write tests,<strong> the client will test your application</strong>, which will have a terrible effect on your company. How can a developer test concurrent situations only by running the code on his local machine? Or test many scenarios that only happen in unusual situations?"
    },
    {
      "type": "quote",
      "html": "We need to look after the stability of all of our code with preview stages."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Chat GPT Opinion about “why we need to write Test”?"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://en.wikipedia.org/wiki/ChatGPT\" target=\"_blank\" rel=\"noreferrer noopener\">Writing a test before releasing the application to the client helps developers identify critical spots in their app and make sure that nothing will go wrong.</a>"
    },
    {
      "type": "paragraph",
      "html": "Moreover, writing tests is not just a one-time affair but a repetitive one. Every code change needs a different set of test scenarios. Writing tests enables developers to automatically check for bugs or problems quickly after each small change without manually running every scenario or testing environment, which greatly reduces the cost and increases the accuracy and stability of applications."
    },
    {
      "type": "paragraph",
      "html": "Also, tests always help when developers need to make bigger changes to the app because they can quickly tell if buyers are still able to use applications as before with full confidence."
    },
    {
      "type": "paragraph",
      "html": "In brief, writing the tests saves a lot of time (by removing manual testing), gives peace of mind, lets you track down problematic areas easily, and helps you develop stable and easy-to-maintain software applications."
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://chat.openai.com/\" target=\"_blank\" rel=\"noreferrer noopener\">https://chat.openai.com/</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Where do we need to write a test?"
    },
    {
      "type": "paragraph",
      "html": "Absolutely, we need unit tests in the Service layer. This means that we don’t need to write tests for the client or controller layer. I saw somebody write tests to connect to the database, but the main question is, “Is it our responsibility to write tests to the Database?” Absolutely not. However, in Integration Tests, we cover the controller layer, too."
    },
    {
      "type": "quote",
      "html": "Start writing tests from the <strong>core of the business</strong> and an <strong>essential part </strong>of the service. If your code doesn’t have tests yet, find a <strong>major part </strong>of your code and then write a <strong>30% test </strong>for the codes."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Unit test"
    },
    {
      "type": "paragraph",
      "html": "The tiny unit usually checks the service layer for TDD, and the check code is valid after other changes happen."
    },
    {
      "type": "paragraph",
      "html": "Although receiving 100% coverage is the dream for every company, in the real world, achieving 70% coverage will be perfect."
    },
    {
      "type": "quote",
      "html": "We need to build a <strong>docker file</strong> for the Unit test in DevOps Pipeline."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Golang testify package"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Golang testify Example"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Example for testing logic without Databases"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "package service_test\nimport (\n\"testing\"\n\"github.com/stretchr/testify/assert\"\n)\nfunc TestService_NameTest(t *testing.T) {\n    type Case struct {\n        name []string\n        want string\n    }\n    cases := []Case{\n        {\n            names: []string{\n                \"Hi\"\n            }, want: \"4422a\",\n        }, {\n            names: []string{\n                \"BYE\"\n            }, want: \"5522b\",\n        },\n    }\n    for _, currentCase := range cases {\n        res := Function(case.names)\n        assert.Equal(t, currentCase.want, res)\n    }\n}"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Run test file"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go test -v ./path=== RUN   TestService_NameTest--- PASS: TestService_NameTest (0.00s)"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Test with the percentage of cover"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go test -v -cover  ./path=== RUN   TestService_NameTest--- PASS: TestService_NameTest\n(0.00s)coverage: 32.1% of statementsok   ./path 0.002s coverage: 32.1% of statements"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Install and run Gotest"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go install gotest.tools/gotestsum@latest"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "gotestsum --junitfile unit-tests.xml"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "✓  path1 (cached)✓  path2(cached)∅  app"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*tiQIuoRo2NDkePP32iJb_Q.png",
      "alt": "Junit result in Gitlab",
      "caption": "Junit result in Gitlab",
      "width": 513,
      "height": 588
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Install and run gocover-cobertura"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go get github.com/boumenot/gocover-cobertura\ngo install github.com/boumenot/gocover-cobertura@latest"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go test -coverprofile=coverage.txt -covermode count ./pathgocover-cobertura < coverage.txt >\ncoverage.xml"
    },
    {
      "type": "paragraph",
      "html": "Write a docker file and execute the test inside of the docker file"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*3zxGRCx096Ks_iqTehmQ1g.png",
      "alt": "How write a Unit test, Integration test, and Performance test for the Golang language?",
      "caption": "",
      "width": 477,
      "height": 175
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*8oEX9D10yqRxejZleusL_Q.gif",
      "alt": "1 percent coverage!",
      "caption": "1 percent coverage!",
      "width": 200,
      "height": 356
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Test unit and coverage Sample"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "gotestsum  --format pkgname --packages=\"./...\" --junitfile /test-results/unit-tests.xmlgo test\n-coverprofile=/test-results/coverage.txt -covermode=count   -coverpkg=./... -v\n./...gocover-cobertura < /test-results/coverage.txt > /test-results/coverage.xml"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*ShY2KDRsJM8s1GzxXTIPkA.jpeg",
      "alt": "https://t.me/programmerjokes",
      "caption": "https://t.me/programmerjokes",
      "width": 720,
      "height": 712
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Write Mock Object"
    },
    {
      "type": "paragraph",
      "html": "Another excellent feature of the <code>testify</code> the package is its mocking capabilities. Mocking effectively allows us to write replacement objects that mock the behaviors of certain objects in our code that we don’t necessarily want to trigger every time we run our test suite."
    },
    {
      "type": "paragraph",
      "html": "A good example of a mock is the link below."
    },
    {
      "type": "paragraph",
      "html": "Auto-generated test&nbsp;:"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "// smsServiceMocktype smsServiceMock struct {    mock.Mock}// Our mocked smsService methodfunc (m\n*smsServiceMock) SendChargeNotification(value int) bool {\nfmt.Println(\"Mocked charge notification function\")    fmt.Printf(\"Value passed in: %d\\n\", value)  //\nthis records that the method was called and passes in the value  // it was called with  args :=\nm.Called(value)  // it then returns whatever we tell it to return  // in this case true to simulate\nan SMS Service Notification  // sent out    return args.Bool(0)}// we need to satisfy our\nMessageService interface// which sadly means we have to stub out every method// defined in that\ninterfacefunc (m *smsServiceMock) DummyFunc() {    fmt.Println(\"Dummy\")}"
    },
    {
      "type": "paragraph",
      "html": "Our code for using the mock service&nbsp;:"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "// TestChargeCustomer is where the magic happens// here we create our SMSService mockfunc\nTestChargeCustomer(t *testing.T) {    smsService := new(smsServiceMock)  // we then define what\nshould be returned from SendChargeNotification  // when we pass in the value 100 to it. In this\ncase, we want to return  // true as it was successful in sending a notification\nsmsService.On(\"SendChargeNotification\", 100).Return(true)  // next we want to define the service we\nwish to test  myService := MyService{smsService}  // and call said method\nmyService.ChargeCustomer(100)  // at the end, we verify that our myService.ChargeCustomer  // method\ncalled our mocked SendChargeNotification method    smsService.AssertExpectations(t)}"
    },
    {
      "type": "paragraph",
      "html": "The command to run the test&nbsp;: <code>go test&nbsp;./... -v</code>"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go test ./... --failfast"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Generate a Mock based on the interface"
    },
    {
      "type": "paragraph",
      "html": "Thankfully, this is where the <a href=\"https://github.com/vektra/mockery\" target=\"_blank\" rel=\"noreferrer noopener\">vektra/mockery</a> package comes to our aide."
    },
    {
      "type": "paragraph",
      "html": "The mockery binary can take the name of any <code>interfaces</code> you may have defined within your Go packages and it’ll automatically output the generated mocks to <code>mocks/InterfaceName.go</code>. This is seriously handy when you want to save yourself a tonne of time and it’s a tool I would highly recommend checking out!"
    },
    {
      "type": "quote",
      "html": "Add mock folder for all services."
    },
    {
      "type": "paragraph",
      "html": "Each service is related to the other service, so use a mock service to test only one service."
    },
    {
      "type": "paragraph",
      "html": "‍‍‍"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "package example_project\nimport (\n\"testing\"\n\"github.com/stretchr/testify/assert\"\n)\nfunc Foo(s Stringer) string {\n    return s.String()\n}\nfunc TestString(t *testing.T) {\n    mockStringer := NewMockStringer(t)\n    mockStringer.EXPECT().String().Return(\"mockery\")\n    assert.Equal(t, \"mockery\", Foo(mockStringer))\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*2UfTeU24QWt0KwBTC07a8Q.png",
      "alt": "How write a Unit test, Integration test, and Performance test for the Golang language?",
      "caption": "",
      "width": 653,
      "height": 79
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Example: Write Mock a service with mockery"
    },
    {
      "type": "paragraph",
      "html": "You can test <code>getFromDB</code> You can either instantiate a testing database or simply create a mock implementation <code>DB</code> using mockery. Mockery can autogenerate a mock implementation that allows us to define assertions on how the mock was used, what to return, and other useful tidbits. We can add a <code>//go:generate</code> directive above our interface:"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "//go:generate mockery --name NameOfInterfacetype NameOfInterface interface {    Get(val string)\nstring}"
    },
    {
      "type": "paragraph",
      "html": "Put “.mockery.yaml” file on top of your project"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "inpackage: Truetestonly: Truewith-expecter: Truekeeptree: False"
    },
    {
      "type": "paragraph",
      "html": "Run the command “<strong><em>go generate” </em></strong>to build a mock file, and then we will have a mock file service."
    },
    {
      "type": "quote",
      "html": "If you want to use mock service, definitely need to use Dependency Injection."
    },
    {
      "type": "code",
      "lang": "go",
      "code": "mockH := mocks.NewMyInterface(t)mockH.EXPECT().MyFuction(ctx, \"aaa\").Return(\"aa\", nil).Once()"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*pMtk4g9gNhriLdtLvKca_A.png",
      "alt": "How write a Unit test, Integration test, and Performance test for the Golang language?",
      "caption": "",
      "width": 567,
      "height": 405
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Using argument matches"
    },
    {
      "type": "paragraph",
      "html": "Sometimes, you don’t care about the specific arguments a mock is called with. With GoMock, a parameter can be expected to have a fixed value (by specifying the value in the expected call), or it can be expected to match a predicate called a Matcher. Matchers are used to represent ranges of expected arguments using a mocked method. The following matches are pre-defined in <em>GoMock</em>:"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "<code>gomock.Any()</code>: matches any value (of any type)",
        "<code>gomock.Eq(x)</code>: uses reflection to match values that are <code>DeepEqual</code> to <code>x</code>",
        "<code>gomock.Nil()</code>: matches <code>nil</code>",
        "<code>gomock.Not(m)</code>: (where <code>m</code> is a Matcher) matches values not matched by the matcher <code>m</code>",
        "<code>gomock.Not(x)</code>: (where <code>x</code> is <em>not</em> a Matcher) matches values not <code>DeepEqual</code> to <code>x</code>"
      ]
    },
    {
      "type": "code",
      "lang": "text",
      "code": "https://gist.github.com/thiagozs/4276432d12c2e5b152ea15b3f8b0012e"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "store.EXPECT().CreateUser(gomock.Any(), gomock.Any()).Times(1)"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mockery example when inputs doesn't have exact value"
    },
    {
      "type": "code",
      "lang": "python",
      "code": "import . \"github.com/stretchr/testify/mock\"proxyMock := mocks.NewProxy(t)proxyMock.On(\"passthrough\",\nmock.AnythingOfType(\"context.Context\"), mock.AnythingOfType(\"string\")).\n    Return(func(ctx context.Context, s string) string {        return s\n    })"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "How to mock with special condition"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "https://pkg.go.dev/github.com/stretchr/testify/mock"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "func MatchedBy"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "func MatchedBy(fn interface{\n}) argumentMatcher"
    },
    {
      "type": "paragraph",
      "html": "MatchedBy can be used to match a mock call based only on certain properties from a complex structure or some calculation. It takes a function that will be evaluated with the called argument and will return true when there’s a match and false otherwise."
    },
    {
      "type": "code",
      "lang": "go",
      "code": "Example: m.On(\"Do\", MatchedBy(func(req *http.Request) bool { return req.Host == \"example.com\" }))"
    },
    {
      "type": "paragraph",
      "html": "|fn| must be a function accepting a single argument (of the expected type) that returns a bool. If |fn| doesn’t match the required signature, MatchedBy() panics."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*Kgp2jxs-EY6_FTPeZ_DVSQ.jpeg",
      "alt": "https://t.me/programmerjokes",
      "caption": "https://t.me/programmerjokes",
      "width": 720,
      "height": 499
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mock Database"
    },
    {
      "type": "paragraph",
      "html": "If your code obeys the dependency injection rules, you can easily inject the database in the <strong>integration test</strong>. This work needs to separate the controller layer from the service layer, too. In another method, you write your service again with the mock service"
    },
    {
      "type": "quote",
      "html": "There is no built-in mocking framework for pgx."
    },
    {
      "type": "quote",
      "html": "But here are three approaches for testing with pgx."
    },
    {
      "type": "quote",
      "html": "First, I typically integrate over the database when possible."
    },
    {
      "type": "quote",
      "html": "Second, when testing lower level functionality, the pgmock package allows mocking the database server. This is very low level and should probably not be used for application level testing, but it is possible."
    },
    {
      "type": "paragraph",
      "html": "<strong>pgxmock</strong> is a mock library implementing <a href=\"https://github.com/jackc/pgx/\" target=\"_blank\" rel=\"noreferrer noopener\">pgx — PostgreSQL Driver and Toolkit</a>. It’s based on the well-known <a href=\"https://github.com/DATA-DOG/go-sqlmock\" target=\"_blank\" rel=\"noreferrer noopener\">sqlmock</a> library for <code>sql/driver</code>."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "GitHub repository:"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "examples:"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mock Redis"
    },
    {
      "type": "paragraph",
      "html": "A mock of Redis can easily be injected and replaced with real Redis."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "GitHub repository Mini Redis:"
    },
    {
      "type": "paragraph",
      "html": "Sometimes, you want to test code that uses Redis without making it a full-blown integration test. Miniredis implements (parts of) the Redis server, which is to be used in unit tests. It enables a cheap, in-memory Redis replacement with a real TCP interface. Think of it as the Redis version of <code>net/http/httptest</code>."
    },
    {
      "type": "code",
      "lang": "go",
      "code": "func mockRedis() *miniredis.Miniredis {\n    s, err := miniredis.Run() if err != nil {\n        panic(err)\n    }\n    return s\n}\nredisServer := mockRedis()redisClient = redis.NewClient(&redis.Options{\n    Addr: redisServer.Addr()\n})"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Sample code for Mini Redis:"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "GitHub repository Redis mock:"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "GitHub example:"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "more explain:"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mock GRPC"
    },
    {
      "type": "paragraph",
      "html": "It is necessary for microservices to mock GRPC to easily write tests in only one service. If I want to write a test for a process in a single micro server, then it is better to mock other services."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Go-micro Mock :"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Example, use a mock in code"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "mockGRPC \"github.com/go-micro/plugins/v4/client/mock\" response := []mockGRPC.MockResponse{\n{Endpoint: \"Foo.Bar\", Response: map[string]interface{}{\"foo\": \"bar\"}}, } clientMock :=\nmockGRPC.NewClient(mockGRPC.Response(\"go.mock\", response))"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Go-micro mock test:"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "A good example of a mock with GRPC:"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "go-mock sample"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "mockGreeterClient.EXPECT().SayHello(    gomock.Any(), // expect any value for first parameter\ngomock.Any(), // expect any value for second parameter).Return(&helloworld.HelloReply{Message:\n“Mocked RPC”}, nil)"
    },
    {
      "type": "paragraph",
      "html": "We use Gomock to mock the client interface (in the generated code) and programmatically set its methods to expect and return pre-determined values. This enables users to write tests around the client logic and use this mocked stub while making RPC calls."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Docker file sample:"
    },
    {
      "type": "code",
      "lang": "dockerfile",
      "code": "FROM golang:1.20WORKDIR /usr/src/appCOPY go.mod go.sum ./RUN go mod download && go mod verifyCOPY .\n.RUN\ngo build -v -o /usr/local/bin/app ./...CMD [\"app\"]"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mock Natsjs"
    },
    {
      "type": "paragraph",
      "html": "because Natjs is built in Golang, instead of using mock use real Natsjs and install it in your docker file."
    },
    {
      "type": "code",
      "lang": "dockerfile",
      "code": "RUN\ngo install github.com/nats-io/nats-server/v2@latest"
    },
    {
      "type": "paragraph",
      "html": "Also, you can execute it in a bash file."
    },
    {
      "type": "code",
      "lang": "text",
      "code": "nats-server -js -m 9090 &export NATS_URL=localhost:4222"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Nats Js test scenario for push back and pull back"
    },
    {
      "type": "paragraph",
      "html": "To test this logic, we need real Nats js, and we want to compare two different methods for fetching data."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*9b0JZ4h-sAiLVkFIx3Fpxg.png",
      "alt": "How write a Unit test, Integration test, and Performance test for the Golang language?",
      "caption": "",
      "width": 590,
      "height": 341
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Integration test"
    },
    {
      "type": "paragraph",
      "html": "The integration test uses a docker to execute the database, cache, check relations, and send interactive data between microservices. Likewise, in the Integration test, microservices call each other and need to send data from one microservice to another microservice. Furthermore, real databases were used instead of mock services. DevOps deploy databases in a docker file and uses Liquibase to migrate, and seeder data into the database, and then the test will execute in the docker. All unit tests and integration tests will run in all merged branches because we want to measure the improvement of code. To visualize the results, we need Junit and Cobertura, which will be explained in the next parts."
    },
    {
      "type": "quote",
      "html": "We need to build a docker file for the integration test in DevOps."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Liquibase seeder"
    },
    {
      "type": "paragraph",
      "html": "Load data from CSV into the database. Also, We can add SQL to insert data."
    },
    {
      "type": "code",
      "lang": "text",
      "code": "<include file=\"seeds/test.sql\" relativeToChangelogFile=\"true\"/>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mock Blockchain"
    },
    {
      "type": "paragraph",
      "html": "Mock blockchain is an excellent way to run blockchain efficiently on local machines and simulate its performance. Core Blockchain has a simulator part that is useful for writing tests, integration tests, or performance tests. Again, we can use a test of blockchain service to examine everything that will be fine."
    },
    {
      "type": "code",
      "lang": "text",
      "code": "backends.NewSimulatedBackend"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://github.com/core-coin/go-core/blob/d89ea7545a2f7400a361e30fd649d91a88bd28d6/accounts/abi/bind/util_test.go\" target=\"_blank\" rel=\"noreferrer noopener\">https://github.com/core-coin/go-core/blob/d89ea7545a2f7400a361e30fd649d91a88bd28d6/accounts/abi/bind/util_test.go</a>"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "backend := backends.NewSimulatedBackend(   core.GenesisAlloc{    crypto.PubkeyToAddress(pub):\n{Balance: big.NewInt(10000000000)},   },   10000000,  )"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "coreTokenAddress, _, _, err := contracts.DeployCoreToken(auth, s.xcbClient, fakeWrappedTokenAddr,\npriceFeedAddr)"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "JUNIT"
    },
    {
      "type": "paragraph",
      "html": "To show the result of the unit test and integration test in the CI CD pipeline, we have to run the test under Junit output."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Execute Junit file"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "gotestsum --junitfile unit-tests.xml"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "GitLab CI CD Example for running Junit"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "A full example of running Junit is CI CD"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*DpU8eQDdCE45nuTH9xuRHg.gif",
      "alt": "https://circleci.com/blog/level-up-go-test-with-gotestsum/",
      "caption": "https://circleci.com/blog/level-up-go-test-with-gotestsum/",
      "width": 590,
      "height": 444
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Install and use Juint in Golang"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go install github.com/jstemmer/go-junit-report/v2@latest"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Run go-junit-report"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "go test -v 2>&1 ./... | go-junit-report -set-exit-code > report.xml"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Coverage cobertura"
    },
    {
      "type": "paragraph",
      "html": "Cobertura is a free Java tool that calculates the percentage of code accessed by tests. It can be used to identify which parts of your Java program are lacking test coverage. It is based on jcoverage."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Cobertura on golang"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "End to End ( Performance Test)"
    },
    {
      "type": "paragraph",
      "html": "End to End is the black test. We need to ensure our application will work perfectly with a lot of clients with no problem. It doesn’t need to be written in the Golang language, and it can be tested with many tools."
    },
    {
      "type": "quote",
      "html": "If we want to use end-to-end test code, we have to call all API endpoints without any UI interactions."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Loadium"
    },
    {
      "type": "paragraph",
      "html": "Smart load testing solutions for your software. Grow with an award-winning load testing tool, master the load testing methodology, and get the most out of your application."
    },
    {
      "type": "paragraph",
      "html": "Simulate the behavior of customers concurrently and send data from all over the world into our application."
    },
    {
      "type": "paragraph",
      "html": "With these tools, we can understand response time by the increase in the number of customers. When a business wants to execute huge advertisements, this is a useful test. we want to prevent bugs before huge amounts of customers use our application."
    },
    {
      "type": "quote",
      "html": "This tool only can call <strong>API</strong> that defines in the backend.It can simulate constant senario to simulate users."
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://github.com/locustio/locust\" target=\"_blank\" rel=\"noreferrer noopener\">Locust</a> is an easy-to-use, scriptable, and scalable performance testing tool. You define the behavior of your users in regular Python code, instead of being constrained by a UI or domain-specific language that only pretends to be real code. This makes Locust infinitely expandable and very developer friendly."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Pact — Integration testing is done properly"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*NWuSev_rpqP7Ix6zy4Iu3g.png",
      "alt": "How write a Unit test, Integration test, and Performance test for the Golang language?",
      "caption": "",
      "width": 1037,
      "height": 859
    },
    {
      "type": "embed",
      "provider": "youtube",
      "url": "https://www.youtube.com/embed/videoseries?list=PLwy9Bnco-IpfZ72VQ7hce8GicVZs7nm0i"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Security Packages test ( dependency check)"
    },
    {
      "type": "paragraph",
      "html": "<strong>Trivy</strong> (<a href=\"https://github.com/aquasecurity/trivy#how-to-pronounce-the-name-trivy\" target=\"_blank\" rel=\"noreferrer noopener\">pronunciation</a>) is a comprehensive and versatile security scanner. Trivy has <em>scanners</em> that look for security issues and <em>targets</em> where it can find those issues."
    },
    {
      "type": "paragraph",
      "html": "Targets (what Trivy can scan):"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "<strong>Container Image</strong>",
        "Filesystem",
        "Git Repository (remote)",
        "Virtual Machine Image",
        "Kubernetes",
        "AWS"
      ]
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*6Gn7vjng89xw6T4PpMhDzA.png",
      "alt": "https://aquasecurity.github.io/trivy/v0.17.2/",
      "caption": "https://aquasecurity.github.io/trivy/v0.17.2/",
      "width": 2532,
      "height": 1846
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Shadow Traffic"
    },
    {
      "type": "paragraph",
      "html": "It means that DevOps capture traffic that comes to our services and develops uses it to enhance the performance of our algorithms."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Behavior Driven Development (BDD) and Functional Testing"
    },
    {
      "type": "paragraph",
      "html": "Subscribe to DDIntel <a href=\"https://ddintel.datadriveninvestor.com/\" target=\"_blank\" rel=\"noreferrer noopener\">Here</a>."
    },
    {
      "type": "paragraph",
      "html": "Visit our website here: <a href=\"https://www.datadriveninvestor.com/\" target=\"_blank\" rel=\"noreferrer noopener\">https://www.datadriveninvestor.com</a>"
    },
    {
      "type": "paragraph",
      "html": "Join our network here: <a href=\"https://datadriveninvestor.com/collaborate\" target=\"_blank\" rel=\"noreferrer noopener\">https://datadriveninvestor.com/collaborate</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Learn go with tests"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Vscode Setting for setting up a test"
    },
    {
      "type": "paragraph",
      "html": "Make&nbsp;.vscode directory in your project."
    },
    {
      "type": "paragraph",
      "html": "Put launch.json file inside the folder."
    },
    {
      "type": "paragraph",
      "html": "and put the JSON below inside the file."
    },
    {
      "type": "paragraph",
      "html": "then press Cntl + F5"
    },
    {
      "type": "code",
      "lang": "json",
      "code": "{    // Use IntelliSense to learn about possible attributes.    // Hover to view descriptions of\nexisting attributes.    // For more information, visit:\nhttps://go.microsoft.com/fwlink/?linkid=830387    \"version\": \"0.2.0\",    \"configurations\": [\n{            \"name\": \"Launch Package\",            \"type\": \"go\",            \"request\": \"launch\",\n\"mode\": \"auto\",            \"program\": \"main.go\",            \"envFile\": \"${workspaceFolder}/.env\"\n}    ]}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "How to edit default go test timeout in Visual Studio Code?"
    },
    {
      "type": "paragraph",
      "html": "You can use<code>\"go.testTimeout\": \"300s\"</code> on settings.json file. It worked for me."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Asnc Problem"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "panic: Fail in goroutine after MYService_Service_Success_Test has completed"
    },
    {
      "type": "paragraph",
      "html": "\"msg”:”Batch Init succeed failed&nbsp;, error: closed pool”,"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "/ Fail marks the function as having failed but continues execution.func (c *common) Fail() {\n    if c.parent != nil {\n        c.parent.Fail()\n    }\n    c.mu.Lock() defer c.mu.Unlock() // c.done needs to be locked to synchronize checks to c.done in\n    parent tests.if c.done {\n        panic(\"Fail in goroutine after \" + c.name + \" has completed\")\n    }\n    c.failed = true\n}"
    },
    {
      "type": "paragraph",
      "html": "The best solution for solving this problem is to write tests in a single process instead of writing the tests in multi tests."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "When Using Natsjs, it is better to set the context timeout to exit from Natsjs"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://www.sohamkamani.com/golang/context-cancellation-and-values/\" target=\"_blank\" rel=\"noreferrer noopener\">https://www.sohamkamani.com/golang/context-cancellation-and-values/</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Why use TestMain for testing in Go?"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*7zBS3JJzmKnF64-sNC1wWA.png",
      "alt": "How write a Unit test, Integration test, and Performance test for the Golang language?",
      "caption": "",
      "width": 608,
      "height": 268
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Go Testing with testify/suite"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "import (\n\"testing\"\n\"github.com/stretchr/testify/suite\"\n)\ntype MySuite struct {\n    suite.Suite\n}\nfunc (suite *MySuite) TestSomething() {\n    // Test something here\n}\nfunc TestSuite(t *testing.T) {\n    suite.Run(t, new(MySuite))\n}"
    }
  ]
}
