The question has been Updated for better explanation to the issue I have,
Simply I have this controller,
[Authorize]
public class IdeaManagementController : Controller
{
private IIdeaManagementService _ideaManagementService;
private ITenantService _tenantService;
private ITagService _tagService;
private IEmployeeIdeaCategoryService _ideaManagementCategoryService;
private static PbdModule _modul = PbdModule.IdeaManagement;
IAuthorizationService _authorizationService;
public IdeaManagementController(
IIdeaManagementService ideaManagementService,
ITenantService tenantService,
ITagService tagService,
IAuthorizationService authorizationService,
IEmployeeIdeaCategoryService ideaManagementCategoryService)
{
_ideaManagementService = ideaManagementService;
_tenantService = tenantService;
_tagService = tagService;
_authorizationService = authorizationService;
_ideaManagementCategoryService = ideaManagementCategoryService;
}
public async Task<IActionResult> IdeaCoordinator()
{
if (!await _authorizationService.AuthorizeAsync(User, "IdeaManagement_Coordinator"))
{
return new ChallengeResult();
}
var ideas = _ideaManagementService.GetByIdeaCoordinator(_tenantService.GetCurrentTenantId());
return View(ideas);
}
}
and simply I need to test the retrned viewResult of the action method IdeaCoordinator but I couldn't simply because if the _authorizationService.AuthorizeAsync validation Method, I tried to mock the method but simply I couldn't because it is an Extension Built In Method , then I tried to make a work around solution by creating a new Interface that implements IAuthorizationService and Mock that customized Interface like that
public interface ICustomAuthorizationService : IAuthorizationService
{
Task<bool> AuthorizeAsync(ClaimsPrincipal user, string policyName);
}
public IAuthorizationService CustomAuthorizationServiceFactory()
{
Mock<ICustomAuthorizationService> _custom = new Mock<ICustomAuthorizationService>();
_custom.Setup(c => c.AuthorizeAsync(It.IsAny<ClaimsPrincipal>(), "IdeaManagement_Coordinator")).ReturnsAsync(true);
return _custom.Object;
}
and Inject it to while I am calling the controller constructor and then I found myself like that :
[Theory]
[InlineData(1)]
public async void IdeaManager_Should_Return_ViewResult(int _currentTenanatID)
{
// Arrange ..
_IdeaManagementControllerObject = new IdeaManagementController
(IdeaManagementServiceMockFactory(_currentTenanatID),
TenantServiceMockFactory(_currentTenanatID),
TagServiceMockFactory(),
AuthorizationServiceMockFactory(),
EmployeeIdeaCategoryServiceMockFactory());
// Act
var _view = await _IdeaManagementControllerObject.IdeaCoordinator() as ViewResult;
// Assert
Assert.IsType(new ViewResult().GetType(), _view);
}
I expected different results because I marked the return result to be true just to ignore this line of code and continue to the Viewresult but while I debugged my Test Method again the compiler got into the validation message as it didn't feel the changes I did on the AuthorizeAsync Method result ..
Thank you so much in advance.
==Solution==
Intro :
“We can not solve our problems with the same level of thinking that created them” - Albert Einstein. and with this adorable saying I would like to inform that I spent about 1 week for solving this problem until I felt it will never solved at this moment, I spent hours of investigation, but after reading an article and after changing the way of thinking , the solution came in 30 mins.
Problem at a glance :
Simply, I was trying to unit test the written above action method, and I have a serious problem related with that I couldn't mock the method "AuthorizeAsync" and simply because it is a built in extension method and because of extension method nature as static method it can never be mocked with the traditional way of mocking classes.
Solution in Details :
To be able to mock this action method I created a static class that contains static delegates and with those delegates I will mock or as it can be said "Wrap" my extension method by a replacement of my static delegates in my unit test class as following.
public static class DelegateFactory
{
public static Func<ClaimsPrincipal, object, string, Task<bool>> AuthorizeAsync =
(c, o, s) =>
{
return AuthorizationServiceExtensions.AuthorizeAsync(null, null, "");
};
}
public Mock<IAuthorizationService> AuthorizationServiceMockExtensionFactory()
{
var mockRepository = new Moq.MockRepository(Moq.MockBehavior.Strict);
var mockFactory = mockRepository.Create<IAuthorizationService>();
var ClaimsPrincipal = mockRepository.Create<ClaimsPrincipal>();
mockFactory.Setup(x => x.AuthorizeAsync(It.IsAny<ClaimsPrincipal>(), It.IsAny<object>(), It.IsAny<string>())).ReturnsAsync(true);
return mockFactory;
}
and at my test method I just called the mocked object in the controller constructor instantiation.
[Fact]
public async void IdeaCoordinator_When_AuthroizedUser_IsNotNull_But_IdeaManagement_Manager_Authorized_Return_View()
{
// Arrange
int approvedByID = data.GetTenantByID(1).TenantId;
_IdeaManagementControllerObject = new IdeaManagementController
(IdeaManagementServiceMockFactory().Object,
TenantServiceMockFactory().Object,
TagServiceMockFactory().Object,
AuthorizationServiceMockExtensionFactory().Object,
EmployeeIdeaCategoryServiceMockFactory().Object);
//Act
IdeaManagementServiceMockFactory().Setup(m => m.GetByIdeaCoordinator(approvedByID)).Returns(data.GetCordinatedEmpIdeas(approvedByID));
ViewResult _view = await _IdeaManagementControllerObject.IdeaCoordinator() as ViewResult;
var model = _view.Model as List<EmployeeIdea>;
// Assert
Assert.Equal(3, model.Count);
Assert.IsType(new ViewResult().GetType(), _view);
}
and as it said, The single greatest cause of happiness is gratitude.I would like to thank Stephen Fuqua for his brilliant solution and article , http://www.safnet.com/writing/tech/2014/04/making-mockery-of-extension-methods.html
Thank you everyone :) !