1

I am new to writing a unit test case. I am getting error on User.Identity. I saw mocking is the resolution for that and I tried which is not working in my case. I have added my code

My Controller

public ActionResult CreateStage ( EnthiranStageViewModel enthiranStage )
{
    if ( ModelState.IsValid )
    {
        Stage stage = enthiran.Insert_Stage(enthiranStage);
        //logging Stage Creation
        util.ApplicationLog(new ViewModel.Logs.ApplicationLogViewModel
        {
         GameCategorys = GameCategory.Enthiran,
         Event = Events.EnthiranStageCreation,
         SessionAttemptId = null,
         UserId = User.Identity.GetUserId<int>( ),
         OptionalParameter1 = enthiranStage.GameId,
         OptionalParameter2 = stage.Id,
         Description = "Enthiran stage created"
        });
        return RedirectToAction("Stages", new
        {
            id = stage.GameId
        });
    }
    return View( );
}

and below is my test case

[TestMethod( )]
public void createStage ( )
{
    EnthiranStageViewModel enthiranStage = new EnthiranStageViewModel
    {
        StageType=0,
        TriggerBeginType = Akton.Areas.Challenge.Models.TriggerType.Manual,
        TriggerEndType= Akton.Areas.Challenge.Models.TriggerType.Manual,
        TimeLimit = new TimeSpan(9, 6, 13),
        TriggerBeginTime= new DateTime(2016, 09, 3, 9, 6, 13),
        TriggerEndTime= new DateTime(2016, 09, 3, 9, 6, 13),
        StartValueType= Akton.Areas.Challenge.Models.StartValueType.Global,
        StageDate= new DateTime(2016, 09, 3, 9, 6, 13),
        Proforma=25,
        GameId=19,
        CreatedTime=new DateTime(2016, 09, 3, 9, 6, 13),
        UpdatedTime= new DateTime(2016, 09, 3, 9, 6, 13),
        StageName="Test",

    };
    EnthiranController controller = new EnthiranController( );
    JsonResult actual = controller.CreateStage(enthiranStage) as JsonResult;
    var result = actual.Data;
    Assert.AreEqual("{ success = True }", result.ToString( ));
}

Here I have to pass the userId in the ViewModel.Logs.ApplicationLogViewModel, I have no idea how to do that.

How do I get the userId which is passing through applicationLogViewModel?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Sriram
  • 59
  • 1
  • 6
  • Check https://stackoverflow.com/questions/40230776/how-to-mock-httpcontext-user/40234602#40234602 – Nkosi Dec 29 '16 at 08:30
  • Check http://stackoverflow.com/a/39453132/5233410 – Nkosi Dec 29 '16 at 08:31
  • You should also take note that the method under test can return either a view result or redirect to action result but the unit test is checking for a JSON result. which will cause `actual` variable to be `null` – Nkosi Dec 29 '16 at 08:38
  • The main reason for the null user is because the method is accessing `User.Identity` but the `User` property of the controller was not setup/arranged in the test method. – Nkosi Dec 29 '16 at 08:49
  • @Nkosi Hello, thanks for the comment, i need to know instead of Json result, if i pass action result, how should i write Assert? for example in my controller i am passing the value then redirecting the page. please see above my controller – Sriram Dec 29 '16 at 10:09
  • ActionResult actual = controller.CreateStage(enthiranStage) as ActionResult; how should i write unit test case for my controller? – Sriram Dec 29 '16 at 10:12

1 Answers1

2

One solution is to change EnthiranController and pass, for example, IUserContext, something like this:

public interface IUserContext
{
    public IPrincipal User {get;}
}

then pass that through constructor to the controller, and use that context to retrieve the user.

ctor EnthiranController(IUserContext userContext)

Then slightly change unit test to mock all these interfaces. Also instead of JsonResult you can use ActionResult or RedirectToRouteResult as it is shown in following example.

[TestMethod( )]
public void createStage ( )
{
    //arrange
    EnthiranStageViewModel enthiranStage = new EnthiranStageViewModel
    {
        StageType=0,
        TriggerBeginType = Akton.Areas.Challenge.Models.TriggerType.Manual,
        TriggerEndType= Akton.Areas.Challenge.Models.TriggerType.Manual,
        TimeLimit = new TimeSpan(9, 6, 13),
        TriggerBeginTime= new DateTime(2016, 09, 3, 9, 6, 13),
        TriggerEndTime= new DateTime(2016, 09, 3, 9, 6, 13),
        StartValueType= Akton.Areas.Challenge.Models.StartValueType.Global,
        StageDate= new DateTime(2016, 09, 3, 9, 6, 13),
        Proforma=25,
        GameId=19,
        CreatedTime=new DateTime(2016, 09, 3, 9, 6, 13),
        UpdatedTime= new DateTime(2016, 09, 3, 9, 6, 13),
        StageName="Test"    
    };

    Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
    //TODO: setup mockPrincipal
    Mock<IUserContext> mockUserContext = new Mock<IUserContext>();
    mockUserContext.Setup(p => p.User).Returns(mockPrincipal.Object);

    EnthiranController controller = new EnthiranController(mockUserContext.Object);

    //act
    var actual = controller.CreateStage(enthiranStage) as RedirectToRouteResult; 

    //assert
    Assert.IsNotNull(actual);
}
Johnny
  • 8,939
  • 2
  • 28
  • 33
  • Hello, thanks for the comment, its working fine, but i need to know instead of Json result, if i pass action result, how should i write Assert? for example in my controller i am passing the value then redirecting the page. – Sriram Dec 29 '16 at 10:01
  • @Sriram if you want to verify that redirect branch is executed then you can verify that `ActionResult` is of type `RedirectToRouteResult `. – Johnny Dec 29 '16 at 10:18
  • once i change the Json result to action result, variable actual getting null reference error. and also i need to redirect that to another page as per controller data. – Sriram Dec 29 '16 at 10:31
  • @Sriram look at the post from Nkosi. That is the way also how you can verify, I will edit my answer to include that peace of code. – Johnny Dec 29 '16 at 10:46
  • @Lepijohnny as you have it updated in your answer I can remove mine. Just make sure to also mention it as one of the changes needed to solve original problem. – Nkosi Dec 29 '16 at 10:53