question

AfaqKanwarMuhammad-6424 avatar image
0 Votes"
AfaqKanwarMuhammad-6424 asked DuaneArnold-0443 answered

Getting Session Null during Unit testing

I am trying to write some unit tests for User Repository CreateUserSession method, in which I set Session for user. When I run the test, I got HttpContext but session object is invalid operation it is failing at this point with a null reference exception. Not entirely sure how to get round this.

Unit Test Method
private readonly User _user;
[Fact]
public void User_should_login()
{
var accessor = Substitute.For<IHttpContextAccessor>();
accessor.HttpContext.Returns(new DefaultHttpContext());

         var fundingPlatformContext = MemoryDbHelper.GetContext();
        var _unitOfWork = new UnitOfWork(fundingPlatformContext, accessor,
         new OptionsWrapper<AppSettings>(new AppSettings()));
         var _contr = new UserController(_unitOfWork);
            
         //prepare
    
            
    
         //act
    
         var loginDto = new LoginDto()
         {
             Email = "test@123.de",
             OrganizationKey = "RB",
             Password = "123456",
             UserId = 1
         };
         Task<User> result = _unitOfWork.User.CreateUserSession(loginDto);
    
         //assert
         Assert.IsType<LoginResponseDto>(result.Result);
    
         var loginData = (result.Result);
    
         Assert.NotNull(loginData);
     }

User Repository with createUsersession method

 public class UserRepository : Repository<User, FundingPlatformContext>, IUserRepository
 {
    
     private readonly FundingPlatformContext _context;
     private readonly IHttpContextAccessor _httpContextAccessor;
     private readonly AppSettings _appSettings;
    
     public UserRepository(FundingPlatformContext context, IHttpContextAccessor httpContextAccessor, IOptions<AppSettings> appSettings) : base(context)
     {
         _context = context;
         _httpContextAccessor = httpContextAccessor;
         _appSettings = appSettings.Value;
     }
    
        
     public async Task<User> CreateUserSession(LoginDto loginDto)
     {
         string error = "";
         try
         {
             string encPwd = EncryptDecryptHelper.Encrypt(loginDto.Password);
             var userDetail = await _context.Users.Include(q => q.FpUserRoles).ThenInclude(r => r.Roles).Include(o => o.Organization).FirstOrDefaultAsync(e => e.Email == loginDto.Email && e.Organization.OrganizationKey == loginDto.OrganizationKey && e.PasswordHash == encPwd);
    
             if (userDetail != null)
             {
                 _httpContextAccessor.HttpContext.Session.SetBoolean("IsLogin", true);
                 _httpContextAccessor.HttpContext.Session.SetId("UserID", userDetail.Id);
                 _httpContextAccessor.HttpContext.Session.SetString("UserName", userDetail.Email);
                  
    
                 var tokenHandler = new JwtSecurityTokenHandler();
                 var key = System.Text.Encoding.ASCII.GetBytes(_appSettings.Secret);
                 var tokenDescriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor()
                 {
                     Subject = new ClaimsIdentity(new Claim[] {
                     new Claim(ClaimTypes.Name, userDetail.FirstName),
                     new Claim(ClaimTypes.Email, userDetail.Email)
                 }),
                     Expires = DateTime.UtcNow.AddHours(8),
                     SigningCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(key), Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature)
                 };
                 var token = tokenHandler.CreateToken(tokenDescriptor);
                 userDetail.PasswordHash = null;
                 userDetail.Token = tokenHandler.WriteToken(token);
                 return userDetail;
             }
             else
             {
                 error = "Invalid user name or password.";
                 return null;
             }
         }
            
         catch (Exception ex)
         {
             error = "Error Occurred: " + ex.Message;
             return null;
         }
     }

Please help me how can I set session so that in CreateUserSession I can set session while unit test

dotnet-aspnet-core-mvc
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

DuaneArnold-0443 avatar image
0 Votes"
DuaneArnold-0443 answered

You're going to have to find a way to mockout HTTPContext.

https://domburf.medium.com/mocking-the-httpcontext-session-object-in-asp-net-core-2-0-7cda5ec134e

To me, the code you have presented in not unit testable. It also breaks unit testing rules, becuase it is accessing the database.

https://www.artima.com/weblogs/viewpost.jsp?thread=126923

Not all code is unit testable.

The repository object itself, EF and some other objects within the repository object need to be mocked out in order to run a successful unit test, and I don't think it can be done.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.