0

I have controller method which calls some other code and passes user info.

  [HttpPost]
  [Route("")]
    public async Task<IHttpActionResult> MyRecords([FromBody] myBody body,
        CancellationToken cancellationToken)
    {
        try
        {
           //some logic;
           var user = GetUser();
           var ready = new CreateRecords(new Execute("Test"), new Contracts.Data.User(user.Id, user.Name));
        }
        catch (Exception e)
        {
            _log.Error("Request failed", e);
            return base.InternalServerError(e);
        }
    }

    public static UserInfo GetUser()
    {
        if (!(Thread.CurrentPrincipal?.Identity is ClaimsIdentity identity))
            return null;

        var name = identity.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.Name)?.Value ?? "";
        var userId = identity.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier)?.Value;
        return null == userId ? null : new UserInfo(int.Parse(userId), name);
    }

Now i am writing unit tests agains that controller method and bit lost on how to pass user information since i dont have any constructor which accepts that information so how to mock this info in the unit test?

This is how the constructor of my controller looks like

 private readonly ILog _log;

    public MyTestController(ILog log)
    {
        _log = log;
    }

This is my test method

 [Test]
    public async Task TestMethod()
    {
        // Arrange
        
        var controller = new MyTestController(new Mock<ILog>().Object);
    }
James
  • 1,827
  • 5
  • 39
  • 69

1 Answers1

1

Your GetUser() reads the static property Thread.CurrentPrincipal, so if you want to manipulate what that static method returns, you have to write said property as well.

Luckily it's publicly-writable, so you can just do:

Thread.CurrentPrincipal = new ClaimsPrincipal(new ClaimsIdentity(
    new[] { 
        new Claim(ClaimTypes.Name, "FooName"), 
        new Claim(ClaimTypes.NameIdentifier, "42") 
    }
));

And then perform the rest of your test.

See also: How can I safely set the user principal in a custom WebAPI HttpMessageHandler?

CodeCaster
  • 147,647
  • 23
  • 218
  • 272