带有 ExceptionFilterAttribute 的 UnitTest ApiController
UnitTest ApiController with ExceptionFilterAttribute
我正在尝试对我的控制器进行单元测试,其中异常被 ExceptionFilterAttribute 捕获并作为 HttpResponseException 启动。
控制器
[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
}
}
异常过滤器
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"
};
}
}
这是我的测试:
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
}
}
问题是 e
仍然是 ArgumentNullException
。当我继续调试时,它甚至没有达到 ExceptionFilter class
我错过了什么吗?
谢谢。
您的测试直接针对控制器。 ExceptionFilterAttribute
取决于服务器。(记住:属性是 Metadata
)
测试行为的方法是使用 IIS 服务器或 SelfHost Server,然后在您的测试中提升服务器 class 并发送请求:
[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);
}
在我看来,除非你的控制器是 public Api
的一部分,否则你不应该出错代码。(原因很简单,这种测试很容易被破坏,它们很慢并且使用昂贵的资源)如果你的控制器是一部分
public Api
您应该通过 Acceptance tests
对其进行测试,然后确认没有任何内容覆盖预期的行为。
如果您仍想测试此行为
那么我想为您提供另一种测试方法:
- 针对
ExceptionFilters
创建 UT。
- 创建一个验证该方法具有
ExceptionFilters
属性的 UT
例如:
[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();
}
优点:
它速度快,不易损坏,不使用昂贵的资源。
缺点:
在生产中,某些设置可能会覆盖预期的行为。
我正在尝试对我的控制器进行单元测试,其中异常被 ExceptionFilterAttribute 捕获并作为 HttpResponseException 启动。
控制器
[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
}
}
异常过滤器
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"
};
}
}
这是我的测试:
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
}
}
问题是 e
仍然是 ArgumentNullException
。当我继续调试时,它甚至没有达到 ExceptionFilter class
我错过了什么吗? 谢谢。
您的测试直接针对控制器。 ExceptionFilterAttribute
取决于服务器。(记住:属性是 Metadata
)
测试行为的方法是使用 IIS 服务器或 SelfHost Server,然后在您的测试中提升服务器 class 并发送请求:
[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);
}
在我看来,除非你的控制器是 public Api
的一部分,否则你不应该出错代码。(原因很简单,这种测试很容易被破坏,它们很慢并且使用昂贵的资源)如果你的控制器是一部分
public Api
您应该通过 Acceptance tests
对其进行测试,然后确认没有任何内容覆盖预期的行为。
如果您仍想测试此行为 那么我想为您提供另一种测试方法:
- 针对
ExceptionFilters
创建 UT。 - 创建一个验证该方法具有
ExceptionFilters
属性的 UT
例如:
[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();
}
优点: 它速度快,不易损坏,不使用昂贵的资源。
缺点: 在生产中,某些设置可能会覆盖预期的行为。