Reputation: 434
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.
Upvotes: 5
Views: 2390
Reputation: 8725
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.
Upvotes: 5