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

How to express using SDHP when playing with Exception and FaultContract ? #134

Open
SilNak opened this issue Mar 23, 2016 · 11 comments
Open
Assignees

Comments

@SilNak
Copy link

SilNak commented Mar 23, 2016

Hi there,

Consider that piece of code:
try { wcfContractInstance.Raise(); } catch(FaultException fex) { Check.That(fex.Detail.Message).IsEqualTo("Invalid Call."); }

The SHDP is currently limited to the exception itself (inner 'templated' object properties stays hidden to the user:
Check.ThatCode ( () => wcfContractInstance.Raise() ).Throws(FaultException);

What solution could be found to enrich NFluent keeping the SDHP ?

Proposition:
Check.ThatCode ( () => wcfContractInstance.Raise() ).Throws(FaultException).WithInnerType().Message.IsEqualTo("Invalid Call.");
Where WithInnerType(): gives you access to all properties the dev wanna check.

This case was identified with a FaultContract coming from WCF, but it applies also to any Templated Exception.

Thanks.

@tpierrain
Copy link
Owner

Hi, What do you think about new assertions like:

Check.ThatCode(() => { clientWCF.MethodA(null); }).Throws<FaultException>().WithInner<ArgumentNullException>();

Or

Check.ThatCode(() => { clientWCF.MethodA(null); }).Throws<FaultException>().Which. ContainsInner<ArgumentNullException>();

Or

Check.ThatCode(() => { clientWCF.MethodA(null); }).Throws<FaultException>().DueToInner<ArgumentNullException>();

@dupdob
Copy link
Collaborator

dupdob commented Mar 23, 2016

I vote for '..DueTo...'. Clear intent orientation, vs the other ones that are more 'descriptive'

@tpierrain
Copy link
Owner

DueTo().

I like it!

@rhwy
Copy link
Collaborator

rhwy commented Mar 23, 2016

I really like the DueTo which make a clear intent

@tpierrain
Copy link
Owner

Ok for the name. Regarding the behaviour now, do we need to search any inner exception of this type whatever its position on the callstack? Do we need to handle the "WCF case" (i.e. to search within the Detail.Type)?

@SilNak
Copy link
Author

SilNak commented Mar 23, 2016

Fine for me too ! Due To... I really like...
Just to be sure you see one stuff.
There is just a trick, in the bloody WCF, sorry Thomas :-), the
FaultException comes with a templated class ExceptionDetail. And the thing
is, that to access the InnerException this goes thru the Detail Property.
Just to make sure you don't miss this.

@rhwy
Copy link
Collaborator

rhwy commented Mar 23, 2016

For me the DueTo is great for the general case.

If that $&@# WCF has a special behavior, I think the better is to create a NFluent plugin (something like nfluent.wcf :-)). It allows you to have a better naming and functionality without creating strange behavior or dependencies.

sounds good?

@tpierrain
Copy link
Owner

Yeah... Bloody WCF!
;-)

@SilNak
Copy link
Author

SilNak commented Mar 23, 2016

Best is to try find a generic way that cover also the special case of WCF.
If we can expose the inner templated class properties, (I don't know if it's possible), that gives a generic way to access Detail or others properties. and this cover also the use cases of other Templated Exceptions.

@tpierrain tpierrain self-assigned this Mar 24, 2016
@SilNak
Copy link
Author

SilNak commented Mar 26, 2016

Hi there,

My first exploration of the code lead me to understand, the 'generic solution' could be a bit 'hot' to implement.

To publish a new idiom to nFluent the following pattern should be followed:
public static ICheckLink<ICheck<T>> **Idiom**<T>(this ICheck<T> check, T expected)

From my understanding, the only way to add new Idioms as an exploration of the templated type, such as ExceptionDetail when dealing with this FaultException<ExceptionDetail>. would be to generates Idioms on the 'fly' ! If we want to avoid the boring job to cover all the possible templatable types.

It could be feasible by reflecting the inner type and generate the Idioms on the fly, then compile it on the fly again, and then executing when the test run goes thru it.

Stays to find a way to express that when writing the code (user side) since it is not known at the time executing as below :

Check.ThatCode(() => { throw new FaultException<ExceptionDetail>( new ExceptionDetail(new ArgumentOutOfRangeException("Range not permitted!"))); }).Throws<FaultException<ExceptionDetail>>().DueToInner<ExceptionDetail>().Message.IsEqualTo("Range not permitted!");
where .Message.IsEqualTo("Range not permitted!") is not known at the compilation time...

Well, T4 lib could be used to generate the code on the fly, a dynamic assembly could be emitted using the magic of .Net,

Stays to express 'a' way for the user to bypass the compiler with (late-binding) : 'dynamic' maybe ?

Well pretty hot and generic and may be not completely feasible, but a Test framework must be 100% testable and this solution could not guaranty that because all uses-cases are not known in advance!

Going back from Pluton to Earth : a pragmatic way to address the bloody use case of WCF is probably to manage the 'special case' of the bloody WCF :-(

@SilNak
Copy link
Author

SilNak commented Mar 27, 2016

Following my previous post, and to address with a pragmatic way the special case of FaultContract, I propose the following derived from DueTo with DueToDetail.

Could look like this:

        [Test]
        public void BloodyWCF_2()
        {
            Check.ThatCode(() => { throw new FaultException<ExceptionDetail>(new ExceptionDetail(new ArgumentOutOfRangeException("Args not in range"))); }).Throws<FaultException<ExceptionDetail>>().DueToDetail<ArgumentOutOfRangeException>().WithMessage("Args not in range");
        }

This will cover the Default behavior when no custom FaultContract has been defined. 80% of the Use Cases...

In case of Custom made Fault Contract the InnerException**_ is not forcibly exposed_**, this depends of the custom implementation.
A clear sample is exposed here

When the dev is going off the beaten track, he can write its custom 'Check' or simply write more verbose code than with nFluent.

What's your mind ?

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

4 participants