Reputation: 283
I have created a simple action filter in my ASP.NET Core application, this action filter is suppose to log user's activity:
public class AuditAttribute : IResultFilter
{
private readonly IAuditService _audit;
private readonly IUnitOfWork _uow;
public AuditAttribute(IAuditService audit, IUnitOfWork uow)
{
_audit = audit;
_uow = uow;
}
public void OnResultExecuting(ResultExecutingContext context)
{
ar model = new Audit
{
UserName = context.HttpContext.User,
//...
};
_audit.Add(model);
_uow.SaveChanges();
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
Now I just wanted to know how can I write unit tests for it. I'm using xUnit
and Mock
Upvotes: 6
Views: 6484
Reputation: 157
The only way I was able to do this was by creating bare-boned concrete classes and testing the HTTPContext result for what I wanted to achieve. Since I was using concrete classes there was no need for Mock
The setup:
[SetUp]
public void SetUp()
{
_actionContext = new ActionContext()
{
HttpContext = new DefaultHttpContext(),
RouteData = new RouteData(),
ActionDescriptor = new ActionDescriptor()
};
}
The test:
[Test]
public void Should_deny_request()
{
// Given
var resourceExecutingContext = new ResourceExecutingContext(_actionContext, new List<IFilterMetadata>(), new List<IValueProviderFactory>());
var attribute = new YourAttribute();
// When
attribute.OnResourceExecuting(resourceExecutingContext);
var result = (ContentResult) resourceExecutingContext.Result;
// Then
Assert.IsTrue(Equals("403", result.StatusCode.ToString()));
}
And this worked for me.
Upvotes: 5
Reputation: 46036
According to your code, to do unit test, you need to mock the HttpContext as well.
BTW this bit doesn't seem right: UserName = context.HttpContext.User
I suppose you meant UserName = context.HttpContext.User.Identity.Name
. Anyway this is how you test method should look like:
public void OnResultExecuting_Test()
{
// Arrange sesction :
var httpContextWrapper = new Moq<HttpContextBase>();
var genericIdentity = new GenericIdentity("FakeUser","AuthType");
var genericPrincipal = new GenericPrincipal(genericIdentity , new string[]{"FakeRole"});
httpContextWrapper.Setup(o=> o.User).Return(genericPrincipal);
var controller = new FakeController(); // you can define a fake controller class in your test class (should inherit from MVC Controller class)
controller.controllerContext = new ControllerContext( httpContextWrapper.Object, new RouteData(), controller );
var audit = new Moq<IUnitOfWork>();
var uow = new Moq<IAuditService>();
// more code here to do assertion on audit
uow.Setup(o=>o.SaveChanges()).Verifiable();
var attribute= new AuditAttribute(audit.Object,uow.Object);
// Act Section:
attribute.OnActionExecuting( filterContext );
// Assert Section:
... // some assertions
uow.Verify();
}
Upvotes: 0