Skip to content

Conversation

@n1l
Copy link
Contributor

@n1l n1l commented Jan 21, 2020

Create public contructors for StackExchange.Redis event args to be able to create tests scenarios based on redis events. Add sealed attribute to other EventArgs for consistency.

Issue with details - #1325

/// <param name="hashSlot">Hash slot.</param>
/// <param name="old">Old endpoint.</param>
/// <param name="new">New endpoint.</param>
public HashSlotMovedEventArgs(EventHandler<HashSlotMovedEventArgs> handler, object sender,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a very unusual API, for specific reasons; I don't think any external caller (for unit testing etc) would need this - or indeed could use this; I wonder if the public constructor should just be:

public HashSlotMovedEventArgs(int hashSlot, EndPoint old, EndPoint @new) : this (null, null, hashSlot, old, new) {}

thoughts?

Copy link
Contributor Author

@n1l n1l Jan 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still this is a public event and someone may be interested to unit-test some scenarios. For testing purpose I don't think the c'tor should be different.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My answer to that, then: is show the scenario that needs that, ideally in a test. Adding something without a demonstrated use-case is ... not a good way to design the API usually.

Copy link
Contributor Author

@n1l n1l Jan 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mgravell this is an outdated comment. I've updated a pr. So yes, I agree with you, handler is no need for this.

/// <param name="failureType">Redis connection failure type.</param>
/// <param name="exception">The exception occured.</param>
/// <param name="physicalName">Connection physical name.</param>
public ConnectionFailedEventArgs(EventHandler<ConnectionFailedEventArgs> handler, object sender, EndPoint endPoint, ConnectionType connectionType, ConnectionFailureType failureType, Exception exception, string physicalName)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to the comment on EndPointEventArgs - I wonder if the public .ctor should not expose handler / sender

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answer is the same.

/// <param name="connectionType">Redis connection type.</param>
/// <param name="exception">The exception occured.</param>
/// <param name="origin">Origin.</param>
public InternalErrorEventArgs(EventHandler<InternalErrorEventArgs> handler, object sender, EndPoint endpoint, ConnectionType connectionType, Exception exception, string origin)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

/// <param name="sender">The source of the event.</param>
/// <param name="endpoint">Redis endpoint.</param>
/// <param name="message">Error message.</param>
public RedisErrorEventArgs(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@mgravell
Copy link
Collaborator

The very unusual construction API here is because of the way that ICompletable works; I can't see any unit-test scenarios where that would be necessary/appropriate. Now, this could just be that I'm being unimaginative, but... I suspect we can drop those and leave more idiomatic APIs.

In particular, I don't want to force us to make an implementation detail part of the public API.

Thoughts and discussion welcome.


Also: it would really help to see these how they are intended to be used, i.e. in a unit test that uses them how you want to.

Copy link
Contributor Author

@n1l n1l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mgravell ok let me create some samples for example

@n1l
Copy link
Contributor Author

n1l commented Jan 21, 2020

Oh, mb you're talking about public ctor's without params at all? Like for testing purpose?

@mgravell
Copy link
Collaborator

mgravell commented Jan 21, 2020

Oh, mb you're talking about public ctor's without params at all? Like for testing purpose?

no, it is just the handler and sender that are atypical; the API here reverses that (because: reasons). You would not usually have those as parameters on classic event args. So I'm saying: if the args has those: create new public .ctors that invoke the existing internal .ctors, passing null for handler and args, but forward onwards any others. If the old .ctor only has those parameters, then yes: that would result in a parameterless constructor.

@mgravell
Copy link
Collaborator

see also: the example I gave for HashSlotMovedEventArgs

@n1l
Copy link
Contributor Author

n1l commented Jan 21, 2020

@mgravell
Yes I've understood the idea a bit later :)

But still I think I need sender becase I want to be aware of the type of the library raised the event. So only handler is not need.

@n1l n1l force-pushed the feature/public-ctor-eventargs branch from f2ff868 to 7088227 Compare January 21, 2020 13:33
@n1l
Copy link
Contributor Author

n1l commented Jan 21, 2020

@mgravell I've updated please take a look.

@n1l
Copy link
Contributor Author

n1l commented Jan 21, 2020

@mgravell Ahh, ok it's not a big deal. Also there are some fails on linux.

…le to create tests scenarios based on redis events.
@n1l n1l force-pushed the feature/public-ctor-eventargs branch from 1091383 to 7a2314b Compare January 21, 2020 14:30
@n1l
Copy link
Contributor Author

n1l commented Jan 21, 2020

@mgravell please take a look again :)

@n1l
Copy link
Contributor Author

n1l commented Jan 22, 2020

@mgravell is everything ok? :)

@mgravell
Copy link
Collaborator

I know you don't mean anything by it, but keep in mind that OSS maintainers aren't around 24/7 to jump on reviews - lost of plates spinning, including jobs, family, sleep, etc; I plan on taking another look as soon as I have a moment, probably later today.

@n1l
Copy link
Contributor Author

n1l commented Jan 22, 2020

@mgravell Thank you! :)

@NickCraver
Copy link
Collaborator

Minor language note here, could you please change all descriptions from "The constructor for testing purpose." to "This constructor is only for testing purposes."?

@n1l
Copy link
Contributor Author

n1l commented Jan 27, 2020

This constructor is only for testing purposes."?

sure!

@mgravell
Copy link
Collaborator

Constructors look good, but there's still nothing test-wise that indicates the intended usage. What makes me nervous is that as a general principle of API design, I usually prefer to see an example usage along with any new API (including new methods/overloads); that's usually how we discover whether the proposed API actually achieves the things we want to demonstrate. Is there any way of adding a meaningful test here? Not just "oh look, I can call a constructor" - but rather: something that actually shows why we're adding it, and that we have achieved what we wanted. If that means adding Moq or whatever to the test project, I'm fine with that...

@n1l
Copy link
Contributor Author

n1l commented Jan 27, 2020

Is there any way of adding a meaningful test here?

Yes of course, I was just a bit lazy to add them because I thought it's obvious, but ok it's not a big deal again.

Not just "oh look, I can call a constructor" - but rather: something that actually shows why we're adding it, and that we have achieved what we wanted.

Do you mean something except tests(documentation, comments samples) or only tests?

@mgravell
Copy link
Collaborator

Do you mean something except tests(documentation, comments samples) or only tests?

I'm just talking about tests here; this isn't an API that needs documentation - just: you're adding this API because you want to do a thing; it would be good to see the thing happening, so we can prove that it is the right API and enables the thing.

@n1l
Copy link
Contributor Author

n1l commented Feb 1, 2020

Hi, @NickCraver , @mgravell !
I've added some tests for the feature. I've removed sealed attribute because substitute mocking framework can't create proxy for a sealed class. Hope it's ok.

So the Idea is - if I have a component which can do some diagnostic for me(logging, pushing events etc) I want to tests it's handlers. But if there is no public c'tors for event args I can't invoke such handlers and test my component.

@mgravell
Copy link
Collaborator

mgravell commented Feb 1, 2020 via email

@mgravell
Copy link
Collaborator

mgravell commented Feb 3, 2020

Merging, thanks

@mgravell mgravell merged commit 162f2b4 into StackExchange:master Feb 3, 2020
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

Successfully merging this pull request may close these issues.

3 participants