i'm trying to UnitTest my controller where an exception is catch by the ExceptionFilterAttribute and launched back as a HttpResponseException.
Controller
[ExceptionFilters] //ExceptionFilterAttribute
public class EleveController : ApiController
{
private IGpiRepository _gpiRepository;
public EleveController(IGpiRepository gpiRepository)
{
_gpiRepository = gpiRepository;
}
[HttpGet]
[Route("{fiche:int}/grouperepere")]
public GroupeRepere GroupeRepere(int fiche) //This What Im trying to test
{
GpiService service = new GpiService(_gpiRepository);
return service.Get(fiche); //Throw an ArgumentNullException when fiche == 0
}
}
ExceptionFilter
public class ExceptionFilters : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
else if (context.Exception is ArgumentNullException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(string.Format("Argument \"{0}\" is null or invalid", ((ArgumentNullException)context.Exception).ParamName)),
ReasonPhrase = "Argument null or invalid"
};
}
}
and this is my test:
private IGpiRepository _gpiRepository;
private Mock<ICallApi> _callApi;
private EleveController _controller;
[TestInitialize]
public void Initialize()
{
_callApi = new Mock<ICallApi>();
_gpiRepository = new GpiRepository(_callApi.Object);
_controller = new EleveController(_gpiRepository);
}
[TestMethod]
public void EleveController__GroupeRepere_WithBadFiche_400BadRequest()
{
string noGroupe = "111";
int fiche = 0;
try
{
GroupeRepere gp = _controller.GroupeRepere(fiche);
Assert.Fail();
}
catch (Exception e)
{
Assert.IsTrue(e is HttpResponseException); // not working --> ArgumentNullException
}
}
The problem is that e
still is an ArgumentNullException
. When i go on debug, it doesn't even reach the ExceptionFilter class
Am i missing something? Thanks.
To unit test an action filter, you have to pass in an action filter context object (which requires a lot of setup). Action filter methods are void, so you have to verify the behavior by inspecting the context object (or dependencies, like a logger, if you are injecting those).
You can either create a unit test project when creating your application or add a unit test project to an existing application. This tutorial shows both methods for creating a unit test project. To follow this tutorial, you can use either approach.
In this article, you will learn about unit testing controllers in Web API. TDD (Test-driven development) is a developmental approach in which TFD (Test-First Development) is there, and where we write a test before writing a code for the production. TDD is also supported by both MVC and Web API.
Finally, in order to apply this at the global level, in other words for all Web API controllers, we will do the following: Add to the filters collection in a global configuration. CRUDWebAPI.MyCustomExceptionFilter ctrlr = new CRUDWebAPI.MyCustomExceptionFilter (); GlobalConfiguration.Configuration.Filters (ctrlr);
It talks about refactoring express api into a RESTful app. To add unit tests, we first move our request specs to request folder, and create models and controllers folders to hold our unit tests. Let’s first test our post and user models.
Notice that the controller includes a constructor that takes as a parameter a list of Product objects. This constructor enables you to pass test data when unit testing. The controller also includes two async methods to illustrate unit testing asynchronous methods.
Your test is directly against the controller. ExceptionFilterAttribute
depends on a server.(remember: attributes are Metadata
)
The way to test the behavior is to use IIS server or SelfHost Server, then raise the server in your test class and send the request:
[TestInitialize]
public void Initialize()
{
_callApi = new Mock<ICallApi>();
_gpiRepository = new GpiRepository(_callApi.Object);
//initialize your server
//set _gpiRepository as a dependency and etc..
}
[TestMethod]
public void EleveController__GroupeRepere_WithBadFiche_400BadRequest()
{
//configure the request
var result = client.ExecuteAsGet<GroupeRepere>(<your request>);
Assert.AreEqual(HttpStatusCode.BadRequest,result.StatusCode);
}
In my opinion you shouldn't error code unless your controller is apart of public Api
.(the reason is simple this kind of tests are very simple to break, thay are slow and thay use expensive resources) if your controller is a part
public Api
you should test it through your Acceptance tests
, then you verify that nothing override the expected behavior.
If you still want to test this behavior then i'd like to offer you an alternative way to test it:
ExceptionFilters
.ExceptionFilters
attributeFor example:
[TestMethod]
public void GroupeRepere_HasExceptionFiltersAttribute()
{
var attribute = typeof (UnitTest2).GetMethod("GroupeRepere").GetCustomAttributes(true);
foreach (var att in attribute)
{
if(att.GetType() is typeof(ExceptionFilters))
{
return;
}
}
Assert.Fail();
}
Pros: it' fast, not so easy to break, it doesn't use expensive reasorces.
Cons: In production some setting could override the expected behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With