I have this small method that helps me establish, if log4net is defined:
private static bool IsLog4netDefined()
{
return ExceptionHelper.Ignore(() => Assembly.Load("log4net,...")) != null;
}
While debugging unit tests, which don't use log4net, this method causes debugger to break on the exception being thrown, which drives me crazy. The exception is of course expected and is ignored.
I don't want to disable this particular exception in Debug -> Exceptions, as it is pretty generic (FileNotFoundException). I don't want to change any global VS settings.
Is there a way (something like pre-processor directive) to disable VS breaking in this method?
How about this?
DebuggerStepThrough attribute on the method that contains the code that you don't want to break on
DebuggerStepThrough attribute solution
Related
I know that it is nonsense (or there is no chance) for variables that its value is unknowable until the runtime.
Let's assume that you have a method like this:
public void Foo (BarEnum barVal)
{
//...
if(barVal == BarEnum.UnappropriateForFooMethod)
throw new BlaBlaException("Invalid barVal for Foo method ->" + barVal);
//...
}
This method will already throw an exception for unappropriate parameter. But I intend to warn developer that before run code and get an exception. Main idea is that. It is not important that if she/he do not care about warnings or turned off the warning messages, her/him code will get an exception anyway.
I guess that it is possible with built-in attributes. Like Obsolete. But I could not find anything...
If there is no attribute for this purpose, I am open to suggestions for custom solutions.
From .NET Framework 4 and later there's something called Code Contracts (on GitHub). Never tried it, but looks like what you seek.
There's also Roslyn. Also haven't work with it, but probably does at least something that you want. Being a super-tool, it is probably a bit unwieldy and verbose for your needs.
One workaround to this problem, without using external tools, is to thoroughly review the code.
Problem:
I have some code that is failing because an object has not been initialized. The solution for this bug is easy to fix, when detected. However, what surprised me is that my elaborate exception handling didn't catch this exception. That meant the exception wasn't logged or handled, and code following the try catch block was never executed. The try...catch block was outside of the transaction, so there was no issue there.
In this particular case, the exception was inside a batch (RunBaseBatch) job. The job handled several unrelated processing tasks. Once the exception conditions were met, the job terminated, so the other unrelated processing tasks were never called.
Does anyone know if it is possible to catch an "object not initialized" exception in Dynamics AX 2009? I read one post that said it may not be possible to catch certain exceptions in AX, however, I hope that is not the case (reference: https://community.dynamics.com/product/ax/f/33/p/16352/23700.aspx#23700).
Code example:
Here is some simplistic code that recreates the issue:
server static void main(Args args)
{
Array arr;
;
info ("debug: before try...catch");
try
{
// ttsbegin; // enable/disable to test with transactions
// arr = new Array(Types::String); // Enabling this line will prevent the exception
arr.exists(3);
// ttscommit; // enable/disable to test with transactions
}
catch (Exception::Internal) // This exception handler was the Magic Sauce!!
{
info ("debug: catch (Exception::Internal)");
}
catch (Exception::Error)
{
info ("debug: catch (Exception::Error)");
}
catch
{
info ("debug: catch");
}
info ("debug: after try...catch");
}
UPDATE 2013-01-29
I am waiting to accept an answer until this question has been viewed more. Thank you for the answers so far.
I know the example I gave was simplistic. This type of bug is easily fixable when it is known. And defensive programming is always a good idea.
However, in the real world, the code where the bug occurred was very complex. The error occurred several levels deep in an overloaded method of a subclass. It occurred in a specific scenario, when an overloaded method corrupted the protected value of a member variable from the super class. That is where the bug occurred in the code, however, it didn't manifest itself until the super class tried to use the member variable again. The bug was summarily fixed when it was detected and tracked down.
Defensively, yes you could check every protected member variable, every time you use it, but that does start to impact performance, code readability, practicality, etc., which is why languages offer exception handling.
The question here, is how can these type of bugs be caught to make code more robust and bullet-proof? In most development environments (C, C++, C#, or Java for example), a try...catch at a top level could be used to catch, log, and clean up ALL unexpected exceptions. So the code would be able to continue processing with the other unrelated tasks. AX is continuing at some level, because the whole system doesn't come to a grinding halt when this bug occurs. However, the code after the catch in this job is not executing because of what appears to be a deficiency in AX/X++.
I am looking for an innovative solution or work-around, if it exists, to catch the "object not initialized" exception (really ALL exceptions) and to continue processing.
You cannot "catch" it in the traditional sense, but you can avoid it happening. Simply test if the object exists before running anything from it:
if(object)
{
// Exists; Execute statements with object here
}
else
{
// Doesn't exist
}
This works because object will be translated as null if it is not initialized.
(Null == 0) == false
If the object is initialized it will have some value other than null.
(!Null != 0) == true
Hope that helps!
You can, but you shouldn't. A behavior like this is almost certainly a bad design of your code, that will inevitably end in more problems in the future.
You need to make your code defensive to this case, making sure the object is instanciated before using it. Otherwise, you're using the catch code to an expected behavior, wich makes no sense.
EDIT 2013/02/18
In complex scenarios like what you're describing, it's usually very hard to get a solution fully controlled. In AX, try..catch statement is quite simplified and in a very large range of situations is not really needed (unlike Java, C#, ... where is always recommended).
This simplification is nice in almost all situations of AX development, as you don't need to waste time on exception handling. Just let them raise, and the InfoLog will handle them on a simple and reliable way.
The big problem comes where you really need this control... when there is not really a way of force it. I'm not sure if this is really an standard issue or it's espected by the product team to work that way, but this cases are always giving troubles in AX. When you need to catch some specific issue you have to be very creative and deffensive to prevent the exception as catching it will become even more creative...
Hope this helps :)
To elaborate a little, as stated in the post you linked to you cannot catch an Object Not Initialized error. However, you can "fix" the code by adding a simple check before attempting to run functions against a variable that you do not control (for example, if you are requesting an Array type as an argument for a function and you expect the function to be called from outside the class).
try
{
if (arr)
arr.exists(3);
}
The if(arr) statement is enough to skip the processing if the object has not yet been instantiated, effectively bypassing the error. However, this will obviously not throw the error further up the chain. If you really wanted, you could make it throw a different error that can be caught, but obviously that is less than ideal.
In this case, since the RunBaseBatch class may not be something you want to modify it would probably be better to make sure the object that is causing the issue is correctly defined before calling the problem method, and finding these errors in testing.
I am wonder if there is an easy way to finish a test after an Assert has failed. We used to use Galileo for all of our automated tested, but we have moved the Visual Studio Test framework. We had a method that would allow a test to fail, but continue on.
public static bool DoAssertAndContinue(Action assert)
{
try
{
assert();
return true;
}
catch (AssertionException ae)
{
ConfigContext.WriteLine(ae.Message);
return false;
}
}
This is what we used before...and it would be called like this:
assertionResults.Add(Automation.Utils.CommonMethods.DoAssertAndContinue(() => Assert.IsTrue(detail.ValidateName(boo, urns))));
I am just trying to figure out the best way to emulate what we had before without having to refactor all of our tests.
Instead of AssertionException, you should now catch UnitTestAssertException which is the base exception for all mstest assert failures.
You can use Try/Catch in MSTest as well. In Catch block you can catch the specific error and print it using Console.Write to know about the error. I would recommend you look into this thread for more details.
EDIT 1: Personally I don't use try/catch to sake of passing my test method. I write a test method to find defect in actual product. So if you are expecting that your calling method will give you some specific exception then I would suggest to use ExpectedException attribute. This is applicable if you are running your test method for single test data.
Now if you want to pass multiple test data into your test method. Then I would suggest go for Data driven test cases. Here you can keep all your test data inside a XML or XLS or in a DB. Then using that input file you can feed multiple test data into your test method. Try not to use try/catch here and for any test data if your calling method send you some exception then see if MSTest will handle it and move to the next test data or not. If it moves then in Test result window you will be able to see why for that specific test data your method get failed. For data driven concept see this link
The MsTest framework throws an exception on a failed assertion. It's propagation out of the unit test method is what causes the test to fail. If you want to continue on a failed assertion you just need to handle that exception and prevent it from escaping the method.
On the advice of Code Analysis in VS to call Dispose on an object (which I wasn't previuosly) I ended up with a method containing this:
using (var favicon = new HtmlLink
{
Href = "~/templates/default/images/cc_favicon.ico"
})
{
favicon.Attributes.Add("rel", "shortcut icon");
Header.Controls.Add(favicon);
}
This confused me slightly, if I dispose this object after adding it to the Controls collection is that such a good idea?
How does this still work? Is it because the Controls.Add method disposes the object after use as opposed to holding on to it?
I would say that this code shouldn't work but if you say it's working then the only things I can think of are:
Header.Controls.Add add a copy of the object so there is no problem disposing the original.
The Dispose method does not clean anything that is used later.
Hope this helps.
If a method on favicon is called that uses any of the unmanaged resources it will give exception.
From msdn:
You can instantiate the resource object and then pass the variable to
the using statement, but this is not a best practice. In this case,
the object remains in scope after control leaves the using block even
though it will probably no longer have access to its unmanaged
resources. In other words, it will no longer be fully initialized. If
you try to use the object outside the using block, you risk causing an
exception to be thrown. For this reason, it is generally better to
instantiate the object in the using statement and limit its scope to
the using block.
using statement msdn
I assume that you code analysis gave you CA2000: Dispose objects before losing scope before you changed the code. The problem is that you shouldn't dispose your object because you want to use it even after returning from the method (it has been added to a collection).
You can either suppress the message using the SuppressMessage attribute or you can rewrite you code to be really paranoid:
var favicon = new HtmlLink { Href = "~/templates/default/images/cc_favicon.ico" };
try {
favicon.Attributes.Add("rel", "shortcut icon");
}
catch {
favicon.Dispose();
throw;
}
Header.Controls.Add(favicon);
The normal flow of this code adds favicon to the collection that is then responsible for disposing it. However, the abnormal flow where favicon.Attributes.Add throws an exception will dispose favicon before propagating the exception.
In most case, because the garbage collector will do its job eventually, you don't need the paranoid version of the code.
Visual Studio Test can check for expected exceptions using the ExpectedException attribute. You can pass in an exception like this:
[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
You can also check for the message contained within the ExpectedException like this:
[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
But when testing I18N applications I would use a resource file to get that error message (any may even decide to test the different localizations of the error message if I want to, but Visual Studio will not let me do this:
[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
The compiler will give the following error:
An attribute argument must be a
constant expression, typeof expression
or array creation expression of an
attribute
Does anybody know how to test for an exception that has a message from a resource file?
One option I have considered is using custom exception classes, but based on often heard advice such as:
"Do create and throw custom exceptions
if you have an error condition that
can be programmatically handled in a
different way than any other existing
exception. Otherwise, throw one of the
existing exceptions." Source
I'm not expecting to handle the exceptions differently in normal flow (it's a critical exception, so I'm going into panic mode anyway) and I don't think creating an exception for each test case is the right thing to do. Any opinions?
I would recommend using a helper method instead of an attribute. Something like this:
public static class ExceptionAssert
{
public static T Throws<T>(Action action) where T : Exception
{
try
{
action();
}
catch (T ex)
{
return ex;
}
Assert.Fail("Exception of type {0} should be thrown.", typeof(T));
// The compiler doesn't know that Assert.Fail
// will always throw an exception
return null;
}
}
Then you can write your test something like this:
[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
OrganizationList organizations = new Organizations();
organizations.Add(new Organization());
organizations.Add(new Organization());
var ex = ExceptionAssert.Throws<CriticalException>(
() => organizations.GetOrganization());
Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}
This also has the benefit that it verifies that the exception is thrown on the line you were expecting it to be thrown instead of anywhere in your test method.
The ExpectedException Message argument does not match against the message of the exception. Rather this is the message that is printed in the test results if the expected exception did not in fact occur.
Just an opinion, but I would say the error text:
is part of the test, in which case getting it from the resource would be 'wrong' (otherwise you could end up with a consistantly mangled resource), so just update the test when you change the resource (or the test fails)
is not part of the test, and you should only care that it throws the exception.
Note that the first option should let you test multiple languages, given the ability to run with a locale.
As for multiple exceptions, I'm from C++ land, where creating loads and loads of exceptions (to the point of one per 'throw' statement!) in big heirachies is acceptable (if not common), but .Net's metadata system probably doesn't like that, hence that advice.
I think you can just do an explicit try-catch in your test code instead of relying on the ExpectedException attribute to do it for you. Then you can come up with some helper method that will read the resource file and compare the error message to the one that comes with the exception that was caught. (of course if there wasn't an exception then the test case should be considered a fail)
If you switch over to using the very nice xUnit.Net testing library, you can replace [ExpectedException] with something like this:
[Fact]
public void TestException()
{
Exception ex = Record.Exception(() => myClass.DoSomethingExceptional());
// Assert whatever you like about the exception here.
}
I wonder if NUnit is moving down the path away from simplicity... but here you go.
New enhancements (2.4.3 and up?) to the ExpectedException attribute allow you more control on the checks to be performed on the expected Exception via a Handler method. More Details on the official NUnit doc page.. towards the end of the page.
[ExpectedException( Handler="HandlerMethod" )]
public void TestMethod()
{
...
}
public void HandlerMethod( System.Exception ex )
{
...
}
Note: Something doesn't feel right here.. Why are your exceptions messages internationalized.. Are you using exceptions for things that need to be handled or notified to the user. Unless you have a bunch of culturally diverse developers fixing bugs.. you shouldn't be needing this. Exceptions in English or a common accepted language would suffice. But in case you have to have this.. its possible :)
I came across this question while trying to resolve a similar issue on my own. (I'll detail the solution that I settled on below.)
I have to agree with Gishu's comments about internationalizing the exception messages being a code smell.
I had done this initially in my own project so that I could have consistency between the error messages throw by my application and in my unit tests. ie, to only have to define my exception messages in one place and at the time, the Resource file seemed like a sensible place to do this since I was already using it for various labels and strings (and since it made sense to add a reference to it in my test code to verify that those same labels showed in the appropriate places).
At one point I had considered (and tested) using try/catch blocks to avoid the requirement of a constant by the ExpectedException attribute, but this seemed like it would lead to quite a lot of extra code if applied on a large scale.
In the end, the solution that I settled on was to create a static class in my Resource library and store my exception messages in that. This way there's no need to internationalize them (which I'll agree doesn't make sense) and they're made accessible anytime that a resource string would be accessible since they're in the same namespace. (This fits with my desire not to make verifying the exception text a complex process.)
My test code then simply boils down to (pardon the mangling...):
[Test,
ExpectedException(typeof(System.ArgumentException),
ExpectedException=ProductExceptionMessages.DuplicateProductName)]
public void TestCreateDuplicateProduct()
{
_repository.CreateProduct("TestCreateDuplicateProduct");
_repository.CreateProduct("TestCreateDuplicateProduct");
}