How to test a unexported (private) function in go (golang)?

Unit TestingGo

Unit Testing Problem Overview


I was interested in creating unit test for "unexported (private) functions" in go. However, its basically really hard to create unit tests form them in the test package because I have to make them "public". Which in the end, defeats the whole point of them being private. The point is that these helper function help modularize and now that they are modular, it would be nice to be able to create unit tests for them without making them available to everyone except the testing package, nice they are not functions that should be accessed or used by anyone else except the testing suite or the actual package itself.

Any suggestions? Is it possible to only export to its own package and 1 additional package or something of that sort in go?

Unit Testing Solutions


Solution 1 - Unit Testing

create a test file within the package

library_test.go

package mypkg

func TestPrivateStruct(t *testing.T){
  pf := private{ "Private Field" }
  ....
}

library.go

package mypkg

type private struct {
  privateField string
}

go test mypkg -v will run your Tests with your private struct

Solution 2 - Unit Testing

if you want to use pkg_test name as a package name for test and still test unexported field a simple trick could be create export_test.go file in your package with package name pkg then export your unexported field in there for example

file code.go

package pkg 

func getFunc(){}

file export_test.go

package pkg 
var GetFunc = getFunc

file code_test.go

package pkg_test
func TestGetFunc(t *testing.T) {
    testFunc:=pkg.GetFunc

	//check your test scenario here
	
}

note that all these files are in the same folder

the solution is inspired from here

Solution 3 - Unit Testing

First, you can have both types of tests in the same location as your package by using the package name for internal tests (eg mypkg) and using the same package name with "_test" appended for "external" tests (eg mypkg_test). Both types of tests must be in files whose name ends in "_test.go".

BUT, the whole point of unit tests is to test the "external interface" (ie public functions) to your package. That is unit tests should always be "white box" tests (see [White Box Testing][1]). That way you can refactor your code and your tests won't break.

Of course, sometimes you want to check internal consistency, which is not possible through the "external interface". For that I have found assertions invaluable. Another possibility would be to add public "diagnostic" function(s) with names that indicate that they are not for normal use.

[1]: http://devmethodologies.blogspot.com.au/2013/11/unit-tests-white-box-testing.html "Unit Tests - White Box Testing"

Solution 4 - Unit Testing

As of Go 1.5 you can use internal packages for shared functions within a package without having to expose them to outside callers.

Simply create a package named internal inside you package, move your shared functions into files inside the internal package and expose them as public functions. Then you can create test files for these functions as you would normally, using the internal_test for the package.

For example:

project/
└── domain/
    ├── logic.go
    ├── logic_test.go
    ├── wisdom.go
    ├── wisdom_test.go
    └── internal/
        ├── shared.go
        └── shared_test.go  

Only code within the domain package would be able to see and access the functions exposed inside the internal package. For a more in depth description, see the proposal or look at the go source code.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCharlie ParkerView Question on Stackoverflow
Solution 1 - Unit TestingfabrizioMView Answer on Stackoverflow
Solution 2 - Unit TestingMajid MohsenifarView Answer on Stackoverflow
Solution 3 - Unit TestingAndrew W. PhillipsView Answer on Stackoverflow
Solution 4 - Unit TestingDaniel ChurmView Answer on Stackoverflow