I have a singleton in my application, but it's published not as a struct directly, but as an interface (because I want to be able to dynamically select the particular implementation upon singleton initialization). Here's the code:
var once sync.Once
var instance defaultConfiguration
type Configuration interface {
GetFoo() string
}
type defaultConfiguration struct {
}
func (dc defaultConfiguration) GetFoo() string {
return "foo"
}
func NewConfiguration() Configuration {
once.Do(func() {
instance = defaultConfiguration{}
})
return instance
}
Then I decided to write a unit-test that would check that NewConfiguration() will actually return the same instance each time:
func TestNewConfigurationSameInstance(t *testing.T) {
configuration1 := NewConfiguration()
configuration2 := NewConfiguration()
if &configuration1 != &configuration2 {
t.Error()
}
}
I thought it would make sense to compare the addresses of the returned instances, however, this test fails.
Then I thought, well, maybe I have to return a pointer to an instance, so I've changed the code to look like this:
func NewConfiguration() *Configuration {
once.Do(func() {
instance = defaultConfiguration{}
})
return &instance
}
But this doesn't even compile: it fails with the error message
cannot use &instance (type *defaultConfiguration) as type *Configuration in return argument:
*Configuration is pointer to interface, not interface
And I've got very confused. Why can't I return a pointer to an interface? Or, why returning defaultConfiguration as Configuration is valid, but returning *defaultConfiguration as *Configuration is not?
And, after all, what is the proper unit-test for my use-case?
Your code should be:
var once sync.Once
var instance *defaultConfiguration
type Configuration interface {
GetFoo() string
}
type defaultConfiguration struct {
}
func (dc *defaultConfiguration) GetFoo() string {
return "foo"
}
func NewConfiguration() Configuration {
once.Do(func() {
instance = &defaultConfiguration{}
})
return instance
}
Since Configuration is an interface and you want a pointer to defaultConfiguration to implement it.
Pointers to interfaces (e.g. *Configuration) are rarely needed. An interface is already a reference value, and it's perfectly fine for a pointer to some type to implement an interface.
For more background on the root issue read this answer or similar resources.
Related
I am new to golang and came from a java background.
Here is my problem today: How to unit test a component that uses a third-party library that doesn't provide an interface in Golang? Here is my concrete example:
I have a class that uses golang mongodb driver to implement some DB operations like below:
package mypackage
type myClientBeingTested struct {
client *mongo.Client
}
func (mc *myClientBeingTested) FindOne(filter interface{}) (*mongo.SingleResult, error) {
result := mc.client.FindOne(context.Background(), filter)
if result.Err() == mongo.ErrNoDocuments {
return nil, nil
} else {
return nil, Errors.New("My own error message")
}
return result, nil
}
Now I'd like to write some unit tests for this method and realized that it's impossible to mock a third party dependency that doesn't have an interface implementation. In the example above, mongo.Client is a struct type. After some researching and thinking, the only possible way seems to be like below:
package mypackage
type myClientBeingTested struct {
client *mongo.Client
}
var findOneFunc = func(client *mongo.Client, ctx context.Context, filter interface{}) (*mongo.SingleResult, error) {
return client.findOne(ctx, filter)
}
func (mc *myClientBeingTested) FindOne(filter interface{}) (*mongo.SingleResult, error) {
result := findOneFunc(mc.client, filter)
if result.Err() == mongo.ErrNoDocuments {
return nil, nil
} else {
return nil, Errors.New("My own error message")
}
return result, nil
}
Then in my unit test I can stub findOneFunc with my own stub like below
findOneFunc = func(client *mongo.Client, ctx context.Context, filter interface{}) (*mongo.SingleResult, error) {
// my own implementation
}
But this seems to be a hack. Is there any authentic/recommended way to handling situations like that? Appreciate your responses!
It should be possible to write your own interface for the methods that you need to use from a struct imported from a 3rd party library.
type MongoClient interface {
FindOne(context.Context, mongo.D) (*mongo.SingleResult, error)
}
type myClientBeingTested struct {
client MongoClient
}
// in tests
type mockMongoClient struct {
// implement MongoClient, pass in to myClientBeingTested
}
However for most apps it provides a better guarantee to run tests against a local or in memory database to verify that everything works end to end. If that becomes too slow it can make sense to mock at the business logic level instead of the database query level.
For example:
type User struct {}
type UserMgmt interface {
Login(email, pass string) (*User, error)
}
// for testing api or workflows
type MockUserMgmt struct {}
// for production app
type LiveUserMgmt struct {
client *mongo.Client
}
In the unit test it would look like:
// user_mgmt_test.go test code
userMgmt := &LiveUserMgmt{client: mongo.Connect("localhost")}
// test public library methods
In api or workflow tests it would look like:
userMgmt := &MockUserMgmt{}
// example pass to api routes
api := &RequestHandler{
UserMgmt: userMgmt,
}
EDIT:
I'm too new to comment on my post, but re your question about mocking the struct, you apply the same principle. If the mongo type is a struct, you can create an interface (even with the same name) and depend on the interface instead of directly depending on the struct. Then via the interface you can mock out the methods you need to.
// The mongo struct you depend on and need to mock
type mongo struct {
someState string
}
// The real world function you need to mock out
func (m *mongo) Foo() error {
// do stuff
return nil
}
// Construct an interface with a method that matches the signature you need to mock
type mockableMongoInterface interface {
Foo() error
}
Now depend on mockableMongoInterface instead of directly on mongo. You can still pass your third party mongo struct to sites where you need it, because go will understand the type via the interface.
This aligns with Adrian's comment on your question.
Current working on creating a Prism.DryIoc.Forms project to try out DryIoc (first time!).
In Xamarin.Forms there is a native DependencyService and to provide a nice way to migrate towards using Prism I would like to add it as a fallback container in case the requsted service type can't be resolved from the main container.
Current I have created a FallbackContainer and pass the instance of IContainerand overrides the methods for IResolver and delegates the rest of the IContainer calls to the instance passed during creation.
So after the default container is created and configured and then do
Container = CreateContainer();
ConfigureContainer();
Container.Rules.WithFallbackContainer(new DependencyServiceContainer(Container));
Is this the preferred method or is there any way just to attach a default IResolver?
Current implementation
public class FallbackDependencyServiceContainer : IContainer
{
private readonly IContainer container;
public FallbackDependencyServiceContainer(IContainer container)
{
this.container = container;
}
public object Resolve(Type serviceType, bool ifUnresolvedReturnDefault)
{
return ResolveFromDependencyService(serviceType);
}
public object Resolve(Type serviceType, object serviceKey, bool ifUnresolvedReturnDefault,
Type requiredServiceType,
RequestInfo preResolveParent, IScope scope)
{
return ResolveFromDependencyService(serviceType);
}
public IEnumerable<object> ResolveMany(Type serviceType, object serviceKey, Type requiredServiceType,
object compositeParentKey,
Type compositeParentRequiredType, RequestInfo preResolveParent, IScope scope)
{
return new[] { ResolveFromDependencyService(serviceType) };
}
private static object ResolveFromDependencyService(Type targetType)
{
if (!targetType.GetTypeInfo().IsInterface)
{
return null;
}
var method = typeof(DependencyService).GetTypeInfo().GetDeclaredMethod("Get");
var genericMethod = method.MakeGenericMethod(targetType);
return genericMethod.Invoke(null, new object[] { DependencyFetchTarget.GlobalInstance });
}
....
}
Thanks and looking forward to test DryIoc since I've read it's supposed to be the fastest out there
Updated answer:
You may directly use WithUnknownServiceResolvers returning DelegateFactory:
var c = new Container(Rules.Default.WithUnknownServiceResolvers(request =>
new DelegateFactory(_ => GetFromDependencyService(request.ServiceType))));
No need to implement IContainer just for that.
I think it may be optimized regarding performance by replacing DelegateFactory with ExpressionFactory. But I need some time to play with the idea.
So from what I've read, you can't test if a function is equal in Go, but I'm trying to solve a test-case issue, so any help in refactoring this would be helpful.
I have a constructor and I'm passing it some configuration values. Based on those configs, it assigns another constructor function to a member of the struct. Later, in a different method, it calls that new constructor. I did it this way because it made it easier to test the methods on the struct, since I could now create a test constructor and reassign the struct member to it, before calling the methods I was testing. Similar to the approach here: Mock functions in Go
Now though, I'm trying to write a test case on the struct constructor and I'm having a hard time figuring out how to test it.
Here's an example:
type requestBuilder func(portFlipArgs, PortFlipConfig) portFlipRequest
type portFlip struct {
config PortFlipConfig
args portFlipArgs
builder requestBuilder
}
func newPortFlip(args portFlipArgs, config PortFlipConfig) (*portFlip, error) {
p := &portFlip{args: args, config: config}
if p.netType() == "sdn" {
p.builder = newSDNRequest
} else if p.netType() == "legacy" {
p.builder = newLegacyRequest
} else {
return nil, fmt.Errorf("Invalid or nil netType: %s", p.netType())
}
return p, nil
}
The 'newSDNRequest' and 'newLegacyRequest' are the new constructors. I can't figure out how to test the newPortFlip method to make sure that's it assigning the right method to the 'builder' member, since you can't test function equality.
My only thought at this point is to have a 'builderType string' member, and just assign it to the name of the new constructor and then I could just test that. Something like:
func newPortFlip(args portFlipArgs, config PortFlipConfig) (*portFlip, error) {
p := &portFlip{args: args, config: config}
if p.netType() == "sdn" {
p.builderType = "newSDNRequest"
p.builder = newSDNRequest
} else if p.netType() == "legacy" {
p.builderType = "newLegacyRequest"
p.builder = newLegacyRequest
} else {
return nil, fmt.Errorf("Invalid or nil netType: %s", p.netType())
}
return p, nil
}
But that seemed rather frivolous, so I figured I should seek a better way before I did that.
Thoughts?
Make portFlip an interface and have newPortFlip construct either an sdnPortFlip or a legacyPortFlip depending on the incoming type. In your test you can then check it's returning the correct concrete type using a type assertion.
If you embed the common type into the SDN and legacy types then you can directly call those methods.
type portFlip interface {
build()
...
}
type portFlipCommon struct {
config PortFlipConfig
args portFlipArgs
}
type portFlipSdn struct {
portFlipCommon
}
type portFlipLegacy struct {
portFlipCommon
}
func (pf *portFlipCommon) netType() { ... }
func (pf *portFlipSdn) build() { ... }
func (pf *portFlipLegacy) build() { ... }
func newPortFlip(args portFlipArgs, config PortFlipConfig) (portFlip, error) {
var pf portFlip
p := &portFlipCommon{args: args, config: config}
if p.netType() == "sdn" {
// Either build directly or define build on the sdn type
pf = &portFlipSdn{*p}
} else if p.netType() == "legacy" {
// Either build directly or define build on the legacy type
pf = &portFlipLegacy{*p}
} else {
return nil, fmt.Errorf("Invalid or nil netType: %s", p.netType())
}
return pf, nil
}
I'm working with Golang, and currently I'm doing some fun unit test with Testify, my file look like this
type myStruct struct {
field_1 string
}
func (self *myStruct) writeFirst() {
//doing something
//modify field_1
self.writeSecond()
}
func (self *myStruct) writeSecond() {
//doing something
}
In this case I'm testing writeFirst() but I'm trying to replace writeSecond() because it is using http stuff that I don't want to use because it access to internet.
I think that use a second struct and set myStruct as anonymous field will be the solution, but it's not working because me second struct and myStruct have a diferent context.
In this case I can't use mocks cause writeSecond is a method of the struct.
My test case looks like this:
func TestWriteFirst(t *testing.T) {
myStc := myStruct{}
assert.Equal(t,"My response", myStc.field_1)
}
All that I want is testing writeFirst without pass to writeSecond()
To illustrate the kind of refactoring mentioned by Not-a-Golfer in the comments, you could consider calling your second function only on an instance that is an interface:
type F2er interface {
Func2()
}
type S struct{ _f2 F2er }
var s = &S{}
func (s *S) f2() F2er {
if s._f2 == nil {
return s
}
return s._f2
}
func (s *S) Func1() {
fmt.Println("s.Func1")
s.f2().Func2()
}
Here: Func1 calls Func2 on s.f2(), not directly s.
If nothing has been set in s, s.f2() returns... itself: s
if s._f2 was replaced by any other struct which implements Func2, s.f2() returns that instance instead of itself.
See a complete example in this playground script.
Output:
TestFunc1
s.Func1
s.Func2
TestFunc1bis
s.Func1
testS.Func2 <=== different Func2 call
I have a generic class for making and processing JSON API requests. I pass in the TParam and TResult template parameters but when I use a derived type it's implementation is not being called.
Here is some code you can throw in a playground to illustrate:
import Cocoa
// Base class for parameters to POST to service
class APIParams {
func getData() -> Dictionary<String, AnyObject> {
return Dictionary<String, AnyObject>()
}
}
// Base class for parsing a JSON Response
class APIResult {
func parseData(data: AnyObject?) {
}
}
// Derived example for a login service
class DerivedAPIParams: APIParams {
var user = "some#one.com"
var pass = "secret"
// THIS METHOD IS CALLED CORRECTLY
override func getData() -> Dictionary<String, AnyObject> {
return [ "user": user, "pass": pass ]
}
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
var success = false
var token:String? = ""
// THIS METHOD IS NEVER CALLED
override func parseData(data: AnyObject?) {
/*
self.success = data!.valueForKey("success") as Bool
self.token = data!.valueForKey("token") as? String
*/
self.success = true
self.token = "1234"
}
}
class APIOperation<TParams: APIParams, TResult: APIResult> {
var url = "http://localhost:3000"
func request(params: TParams, done: (NSError?, TResult?) -> ()) {
let paramData = params.getData()
// ... snip making a request to website ...
let result = self.parseResult(nil)
done(nil, result)
}
func parseResult(data: AnyObject?) -> TResult {
var result = TResult.self()
// This should call the derived implementation if passed, right?
result.parseData(data)
return result
}
}
let derivedOp = APIOperation<DerivedAPIParams, DerivedAPIResult>()
let params = DerivedAPIParams()
derivedOp.request(params) {(error, result) in
if result? {
result!.success
}
}
The really weird thing is that only the DerivedAPIResult.parseData() is not called, whereas the DerivedAPIParams.getData() method is called. Any ideas why?
UPDATE: This defect is fixed with XCode 6.3 beta1 (Apple Swift version 1.2 (swiftlang-602.0.37.3 clang-602.0.37))
Added info for a workaround when using XCode 6.1 (Swift 1.1)
See these dev forum threads for details:
https://devforums.apple.com/thread/251920?tstart=30
https://devforums.apple.com/message/1058033#1058033
In a very similar code sample I was having the exact same issue. After waiting through beta after beta for a "fix", I did more digging and discovered that I can get the expect results by making the base class init() required.
By way of example, here is Matt Gibson's reduced example "fixed" by adding the proper init() to ApiResult
// Base class for parsing a JSON Response
class APIResult {
// adding required init() to base class yields the expected behavior
required init() {}
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
}
class APIOperation<TResult: APIResult> {
init() {
// EDIT: workaround for xcode 6.1, tricking the compiler to do what we want here
let tResultClass : TResult.Type = TResult.self
var test = tResultClass()
// should be able to just do, but it is broken and acknowledged as such by Apple
// var test = TResult()
println(test.self) // now shows that we get DerivedAPIResult
}
}
// Templated creation creates APIResult
let derivedOp = APIOperation<DerivedAPIResult>()
I do not know why this works. If I get time I will dig deeper, but my best guess is that for some reason having required init is causing different object allocation/construction code to be generated that forces proper set up of the vtable we are hoping for.
Looks possibly surprising, certainly. I've reduced your case to something rather simpler, which might help to figure out what's going on:
// Base class for parsing a JSON Response
class APIResult {
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
}
class APIOperation<TResult: APIResult> {
init() {
var test = TResult()
println(test.self) // Shows that we get APIResult, not DerivedAPIResult
}
}
// Templated creation creates APIResult
let derivedOp = APIOperation<DerivedAPIResult>()
...so it seems that creating a new instance of a templated class with a type constraint gives you an instance of the constraint class, rather than the derived class you use to instantiate the specific template instance.
Now, I'd say that the generics in Swift, looking through the Swift book, would probably prefer you not to create your own instances of derived template constraint classes within the template code, but instead just define places to hold instances that are then passed in. By which I mean that this works:
// Base class for parsing a JSON Response
class APIResult {
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
}
class APIOperation<T: APIResult> {
var instance: T
init(instance: T) {
self.instance = instance
println(instance.self) // As you'd expect, this is a DerivedAPIResult
}
}
let derivedOpWithPassedInstance = APIOperation<DerivedAPIResult>(instance: DerivedAPIResult())
...but I'm not clear whether what you're trying should technically be allowed or not.
My guess is that the way generics are implemented means that there's not enough type information when creating the template to create objects of the derived type from "nothing" within the template—so you'd have to create them in your code, which knows about the derived type it wants to use, and pass them in, to be held by templated constrained types.
parseData needs to be defined as a class func which creates an instance of itself, assigns whatever instance properties, and then returns that instance. Basically, it needs to be a factory method. Calling .self() on the type is just accessing the type as a value, not an instance. I'm surprised you don't get some kind of error calling an instance method on a type.