[ExpectedException(typeof(AnExceptionBaseException))] - c#

I wrote a unit test in such a way that it should throw AnException or AnotherException, both deriving from AnExceptionBaseException. I then proceeded to add an ExpectedExceptionAttribute for the base exception, only to find that my test will still be marked as failed.
Test Name: Call_Should_Throw_If_Device_Is_Not_Ready Test
...
Result Message: Test method
DiskManagementTests.DiskFreeSpaceTests.Call_Should_Throw_If_Device_Is_Not_Ready
threw exception System.IO.FileNotFoundException, but exception
System.IO.IOException was expected. Exception message:
System.IO.FileNotFoundException: The device is not ready. (Exception
from HRESULT: 0x80070015)
This seems like a reasonable design decision because, in this particular case, the exception is generated from an HRESULT return code. That makes it nearly impossible to determine which exception will be thrown. At least not without copying the code logic from the unit that my test is supposed to ...test.
My code (I believe this can throw either FileNotFound or DirectoryNotFound):
[TestMethod]
[ExpectedException(typeof(IOException))]
public void Call_Should_Throw_If_Device_Is_Not_Ready()
{
foreach (DriveInfo drive in DriveInfo.GetDrives().Where(drive => !drive.IsReady))
{
DiskFreeSpace diskFreeSpace = DiskManagement.GetDiskFreeSpace(drive.RootDirectory.FullName);
Assert.Fail("API call did not fail even though the drive reports that it is not ready.");
}
Assert.Inconclusive("All drives were ready. Try testing with an empty disc drive.");
}
Do I need to reconsider the way I write unit tests?
EDIT
This scenario is supported after all. All it really took was setting AllowDerivedTypes to true.
[TestMethod]
[ExpectedException(typeof(IOException), AllowDerivedTypes = true)]
public void Call_Should_Throw_If_Device_Is_Not_Ready()
{
// ...
}

You can create your own ExpectedException attribute that will check if the thrown exception inherites the Exception defined in the attribute.
public sealed class MyExpectedException : ExpectedExceptionBaseAttribute
{
private Type _expectedExceptionBaseType;
public MyExpectedException(Type expectedExceptionType)
{
_expectedExceptionBaseType = expectedExceptionType;
}
protected override void Verify(Exception exception)
{
Assert.IsNotNull(exception);
Assert.IsTrue(exception.GetType().IsInstanceOfType(typeof(_expectedExceptionBaseType)) ||
exception.GetType().IsSubclassOf(typeof(_expectedExceptionBaseType)));
}
}
and change the attribute to your test:
[MyExpectedException(typeof(IOException))]

Related

NUnit and ability to ignore failed test without exception

I'm working on a project where I have to use something like soft assertion in NUnit in C#.
I need to implement a feature which says that if a test failed, go to the next test without showing exception but note that this test was failed.
I know that it's inadvisable to use multiple asserts but it's necessary because I got a form where f.e field with surname can fail but next tests are independent and should still run.
public class SoftAssertionTest
{
public static void AreEqual(object expected, object actual)
{
try
{
Assert.AreEqual(expected, actual);
}
catch (Exception e)
{
//Catch exception but remember that test failed and got to the
//next
}
}
}
Expected result is that all tests run without exceptions but finally result show Fail status.
[TestFixture]
public class TestClass
{
[Test]
public static void Test()
{
SoftAssertionTest.AreEqual(1, 2);
SoftAssertionTest.AreEqual(3, 4);
}
}
Any ideas?
NUnit 3 has Assert.Warn if you just want to warn on failures and Assert.Multiple if you want to run multiple asserts and fail the test if any of the individual asserts fail, but ensure that all of the asserts are run.
Try SoftAssertion
SoftAssert softAssert = new SoftAssert();
softAssert.True(false);
softAssert.False(true);
softAssert.NotNull(null);
softAssert.VerifyAll();

VerifyAll() with Throws<T>() in Moq

I have a Mock object whose method I'm trying to setup by throwing an Exception when executed, for a particular unit test case using the Moq framework.
var mockMySvc = new Mock<IMySvc>();
mockMySvc
.Setup(x=>x.SomeMethod())
.Throws<Exception>();
//Execution of some code
//At the assertions
mockMySvc.VerifyAll();
At runtime, the code complains about all the expections of mockMySvc not having been met despite the exception being thrown. Am I missing something or does the .VerifyAll() method not work with the .Throws() functionality.
I don't know about your way of setting it up, but I always do it this way:
Assert.Throws<Exception>(() => myclass.SomeMethod());
This way you don't need to verify anything.
Based on your comment this is how you make sure the exception is thrown inside the method, so that you can check your code inside catch blocks.
[Test]
public void Test1()
{
_filmService.Setup(f => f.FindById(It.IsAny<int>())).Throws<Exception>();
_filmController.Test();
_filmService.Verify(f => f.Exists(It.IsAny<Film>()), Times.Once);
}
Actual code:
public ActionResult Test()
{
try
{
_filmService.FindById(-1);
}
catch (System.Exception)
{
_filmService.Exists(null);
}
return View();
}
This is just an example I tested in my code and it works correctly.

What is the right time to throw an exception in an API?

I'm building a API for my pet software and I'm in the following situation:
A service that use another service. I have a service that use another service for load a Assembly, should I throw a exception in the service that load a assembly or on the service that use that service?
AssemblyService:
public class AssemblyService : IAssemblyService
{
public Assembly Load(string assemblyName)
{
Assembly assembly;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
assembly = null;
}
return assembly;
}
...
}
Service that use AssemblyService:
public class CommandService : ICommandService
{
private readonly IAssemblyService assemblyService;
public CommandService(IAssemblyService assemblyService)
{
this.assemblyService = assemblyService;
}
public CommandOutput Process(string inputCommand, string requestInfo)
{
string commandName = GetAssemblyName(inputCommand);
string args = GetArgs(inputCommand);
Assembly assembly = assemblyService.Load(commandName);
if (assembly == null) throw new UnknownCommandException(commandName);
ICommand command = assemblyService.GetCommand(assembly);
return command.Execute(args, requestInfo);
}
#region Private methods
...
#endregion
}
Should I throw the exception in AssemblyService or CommandService like the above example?
I'm trying to learn how to handle a exception, in the above example the line assembly = Assembly.Load(assemblyName); can throw ArgumentNullException, ArgumentException, FileNotFoundException, FileLoadException and BadImageFormatException. Should I handle all these exceptions?
UnknownCommandException(commandName) is a custom exception.
Other question: Anyone who's using my API could know when a method could throw a exception? I see placing the mouse over any methods of .Net Framework you will see if the method could throw a exception. Could this works with methods of my API?
Your title is about throwing exceptions but you actually seem to be talking about catching exceptions. You should generally not catch exceptions unless you can do something meaningful to rectify the condition that caused the exception to be thrown in the first place, and in that case you should only catch the explicit exception types that you can handle.
There are two things to think about here:
Will the normal flow of the application be abruptly halted to the point where it will no longer work? Exceptions are exactly that - a notification that something exceptional (out of the ordinary, abnormal, etc.) has happened. If it isn't exceptional, don't throw an exception. If the user can continue to use the program without noticing, don't use an exception.
How you comment the method declaration will affect this. There should be some markup tags for the comments that will allow you to explain what exception will be thrown and under what circumstances it will be thrown. They look like this:
/// <exception cref="ExceptionTypeGoesHere"></exception>
I normally try and avoid using exceptions to control the flow of the program. Your program uses an exception to convert it to a result variable and then converts that back to an exception. Why not stick with exceptions all the way? I would change it as follows:
public class AssemblyService : IAssemblyService
{
public Assembly Load(string assemblyName)
{
return Assembly.Load(assemblyName);
}
}
public class CommandService : ICommandService
{
private readonly IAssemblyService assemblyService;
public CommandService(IAssemblyService assemblyService)
{
this.assemblyService = assemblyService;
}
public CommandOutput Process(string inputCommand, string requestInfo)
{
string commandName = GetAssemblyName(inputCommand);
try
{
string args = GetArgs(inputCommand);
Assembly assembly = assemblyService.Load(commandName);
ICommand command = assemblyService.GetCommand(assembly);
return command.Execute(args, requestInfo);
}
catch (Exception ex)
{
//Log original exception or add to inner exception
throw new UnknownCommandException(commandName);
}
}
}
api as the name suggests is the gateway to an application. if an error occurs in the api, it is most useful for the api to tell the consumer why, where and when the error happened i.e. api throws the exception out. it is up to the consumer to catch this and tell its users what to do or if the business logic is defined well the consumer will calculate alternative execution paths. this is my rule of thumb
in the example above the assembly load service should throw the error out. If you handle this in the api, then the consumer will never learn :)
for general guidelines to exception handling look here in Msdn

How to get business exception from wcf?

How can I test for this exception as returned from a WCF call?
I have this error class.
[Serializable]
public class PermissionDenied_Error : Exception
{
public PermissionDenied_Error() : base("You are not approved.") { }
}
In my Service, I am throwing it.
if (notApproved)
{
throw new FaultException<PermissionDenied_Error>(new PermissionDenied_Error()
, new FaultReason("Permissions Denied!"));
}
In my test, I am expecting it.
[Test]
[ExpectedException(typeof(FaultException<PermissionDenied_Error>))]
Current result is:
Expected: System.ServiceModel.FaultException`1[[PermissionDenied_Error
, Project.API, Version=1.0.4318.24332, Culture=neutral, PublicKeyToken=null]]
but was: System.ServiceModel.FaultException : Permissions Denied!
Your PermissionDenied_Error should be a data contract. It should not be derived from Exception.
Also,you need to place the FaultContractAttribute on your operation contract so that the client knows to expect an exception.
Added by Valamas
public interface IAccess
{
[OperationContract]
[FaultContract(typeof(PermissionDenied_Error))]
DtoResponse Access(DtoRequest request);
}
in WCF simply does not work like that.
there are articles around explaining how to setup and use FaultExceptions
check this step by step here: Exception Handling in Windows Communication Framework and Best Practices
Using the ExpectedException attribute is a bad practice. Instead of using this:
[Test]
[ExpectedException(typeof(FaultException<PermissionDenied_Error>))]
try doing:
[Test]
public void Test1()
{
.....
try{
WfcServiceCall(...);
Assert.Fail("a FaultException<PermissionDenied_Error> was expected!");
}catch(FaultException<PermissionDenied_Error>){
Assert.Sucess();
}catch(Exception e){
Assert.Fail("Unexpected exception!")
}
}

Custom exception class to alert errors and log

I am writting an API for some data manipulation these days and I have faced a question that I cannot answer myself :D
I have made an exception class that extends the .net Application Exception class because I want to add some functionality there to be executed everytime the API throws an exception.
For example I want to alert the error message and stacktrace via sms and email and I want to log the inner exception via Log4net. I don't know if this is a good aproach to use with the custom exception class or if I overused the meaning of the custom exceptions.
I have read this article about how to extend the Exception in c#
so here we go with my example of code :
public class CustomExceptionClass : Exception
{
/// <summary>
/// I use custom functionality here everytime this exception occures
/// </summary>
/// <param name="errorMessage">error message</param>
/// <param name="innerEx">Inner exception that cause this exception</param>
public MyCustomException(string errorMessage, Exception innerEx) : base(errorMessage, innerEx)
{
//log exception
_log.ErrorFormat(errorMessage, innerEx);
//alert via sms and email
AlertMailer.SendAlertMessage(errorMessage, innerEx, innerEx.Message);
}
}
I think that doing logging and alerting by throwing a custom exception is a valid technique.
However, you shouldn't do the logging and alerting in the exception constructor. Instead you should catch the custom exception in all entry-points to your API and do the logging and alerting in the catch block. For example:
void MyApiFunction()
{
try
{
// do data manipulation
}
catch(MyCustomException ex)
{
_log.ErrorFormat(ex.ErrorMessage, ex.InnerEx);
AlertMailer.SendAlertMessage(ex.ErrorMessage, ex.InnerEx);
}
}
I would recomend you to use AOP instead.
PostSharp exception handling
Custom exceptions should be used to define different types of exception.
Exceptions from the database
Exceptions from file io
Exceptions from web services
They should be very simple, and contain no other logic than assigning variables. Why? Because if the exception constructor throws another exception you are going to have a hard time tracing it.
The ways i handle those exceptions are:
AOP (Spring.NET)
Specific try/catches
The global exception handler
In a program
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
try {
//do something
} catch(Exception e) {
//log error
}
}
}
}
Or in a web site
public class ApplicationErrorModule : IHttpModule {
public void Init(HttpApplication context) {
context.Error += new EventHandler(context_Error);
}
private void context_Error(object sender, EventArgs e) {
//log error
}
}
Heavy treatments like logging and sending an email don't belong in the constructor of the exception. You should instead handle the exception using AOP as #petro suggested, or in a catch statement.

Categories