Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocking hdfs.Client in test suites #95

Closed
rrix opened this issue Jan 10, 2018 · 2 comments
Closed

Mocking hdfs.Client in test suites #95

rrix opened this issue Jan 10, 2018 · 2 comments

Comments

@rrix
Copy link

rrix commented Jan 10, 2018

Howdy,

First of all, thanks for writing and maintaining this library, it's a boon. :)

I'm trying to design a unit-test for a pile of code that uses hdfs.Client, such that it can run in an environment without an hadoop cluster (travis, jenkins, local laptop), and I'm curious your thoughts on how to do this, because I'm running up against some trouble on it because of the lack of interface definitions within the library. I can almost get around this by defining an interface which hdfs.Client adheres to and then pointing gomock at that, but there are certain things that Go's type system simply won't let me mock.

For example, if I define an interface which hdfs.FileReader implements, I cannot use mocks that implement that interface in the return arguments to client.Open() since that returns the struct directly, rather than an interface which the struct implements:

func TestFetchFile(t *testing.T) {
	assert := assert.New(t)
	ctrl := gomock.NewController(t)
	mock := client.New(t) // mock implementing the same interface as hdfs.Client
	client := mock.Build()

	// client.Open(url) should return an hdfs.FileReader, which I need a mock for, I think, to
	// capture the calls within *that*

	// hdfs.FileReader implements hdfsl.FileReaderIface
	mock.Open().Stub(func(name string) (hdfsl.FileReaderIface, error) {
		return mock_hdfs.NewMockFileReaderIface(ctrl), nil
	})
}

This fails to compile as:

hdfs_test.go:24:19: cannot use func literal (type func(string) ("[redacted gopath]/hdfs".FileReaderIface, error)) as type client.openStub in argument to mock.Open().Stub

this is because openStub is of type type openStub func(arg0 string) (*hdfs.FileReader, error)

And so, I don't know how to generate mocks for this thing such that I can have a mock FileReader from which I can stub the read/write/etc calls. Is there a solution that I can do within my code to create mocks which satisfy the golang type system (my initial assumption is "no"), and if not, is it possible to define interfaces for the return types within the library and refer to them instead of the struct implementations?

@colinmarc
Copy link
Owner

Hi @rrix,

While I see your predicament, I can't really foresee changing the library just to make it easier to mock in other libraries. This is a problem with much of the go stdlib, as well (exposing structs instead of interfaces).

Going to close this, but please feel to reopen if you have another suggestion.

@xiehuc
Copy link

xiehuc commented Jun 2, 2021

could use gomonkey

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants