如何使用mock获取会话值? [英] How to get session value using mock?

查看:157
本文介绍了如何使用mock获取会话值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用c#.Net Core编写API



我的一个API用于生成验证码然后存储到会话中,我正在使用Redis来在这里存储会话。



现在我正在尝试为API编写单元测试。

导致需要通过登录API验证码,所以我需要从会话中获取验证码值。

我正在使用Moq编写单元测试。

我的代码如下:



Captcha api:

I'm writing APIs using c#.Net Core

One of my APIs is used to generate captcha then store to the session, I'm using Redis to store session here.

And now I'm trying to write a unit test for the APIs.
Cause the login API needed to pass captcha, so I need to get the captcha value from the session.
I'm using Moq to write the unit test.
My code is below:

Captcha api:

ILogger<CommonApiController> _logger;
private readonly ISessionWapper _sessionWapper;
string _captcha;

public CommonApiController(ISessionWapper sessionWapper, BaseContext db, IOptions<JwtSetting> options, ILogger<CommonApiController> logger,
            IOptions<SettingModel> sysSetting)
            : base(db, options, logger, sysSetting)
        {
            _logger = logger;
            _sessionWapper = sessionWapper;
        }
public CommonApiController(ISessionWapper sessionWapper, ILogger<CommonApiController> logger)
          : base()
        {
            _logger = logger;
            _sessionWapper = sessionWapper;
        }

[HttpGet("Captcha")]
[ProducesResponseType(typeof(FileResult), 200)]
public async Task<FileResult> GetCaptcha()
{
            try
            {
                var captcha = Captcha.GenerateRandomText(4);
             
                await _sessionWapper.Set(captcha);
                var session = await _sessionWapper.Get();
                _captcha = session;
                _logger.LogDebug(session);
                return File(Captcha.GenerateCaptchaImage(captcha), "image/gif");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.StackTrace);
                return File("ERROR", "image/gif");
            }
        }





会话助手:



Session helper:

public static class SessionExtensions
{
    public static void SetObject<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T GetObject<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
    }
}
public interface ISessionWapper
{
    CaptchaSessionModel Captcha { get; set; }
    Task<string> Get();
    Task Set(string value);
}
public class SessionWapper : ISessionWapper
{
    private static readonly string _captchaKey = "captchaKey";
    private readonly IHttpContextAccessor _httpContextAccessor;

    public SessionWapper(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    public void Clear()
    {
        Session.Clear();
    }
    private ISession Session
    {
        get => _httpContextAccessor.HttpContext.Session;
    }
    public async Task<string> Get()
    {
        await _httpContextAccessor.HttpContext.Session.LoadAsync();
        return Captcha.value;
    }
    public async Task Set(string value)
    {
        Captcha = new CaptchaSessionModel { value = value };
        await _httpContextAccessor.HttpContext.Session.CommitAsync();
    }
    public CaptchaSessionModel Captcha
    {
        get => Session.GetObject<CaptchaSessionModel>(_captchaKey);
        set => Session.SetObject(_captchaKey, value);
    }

}
public struct CaptchaSessionModel
{
    public string value { get; set; }
}





登录Api:



Login Api:

private readonly ISessionWapper _sessionWapper;

ILogger<LoginController> _logger;

public LoginController(ISessionWapper sessionWapper, BaseContext db, IOptions<JwtSetting> options, ILogger<LoginController> logger, IOptions<SettingModel> settingModel)
            : base(db, options, logger, settingModel)
        {
            _logger = logger;
            _sessionWapper = sessionWapper;
        }

[HttpPost("Login/Login")]
        [ProducesResponseType(typeof(DisplayResponseLogin), 200)]
        public async Task<IActionResult> Login([FromBody]LoginRequestModel model)
        {
            try
            {
                var session = await _sessionWapper.Get();
                _logger.LogDebug(JsonConvert.SerializeObject(_sessionWapper.Captcha));

                _logger.LogDebug(session);
                if (string.IsNullOrEmpty(session) || !model.captcha.Equals(session))
                {
                    return Result(new BaseDalResponseModel { status = MobileHis.Enums.ResponseStatus.CaptchaIncorrect_3 });
                }
                
//some login code ....

                var now = DateTime.UtcNow;

                JwtHelper jwtHelper = new JwtHelper(dal, _options);
                var encodedJwt = jwtHelper.GenerateToken(acc, model.remember);//, apis);

                var response = new LoginResponseModel
                {
                    access_token = encodedJwt,
                    expires_in = (int)_options.Expire,
                   
                };
               

                return Result(new BaseDalResponseModel { status = MobileHis.Enums.ResponseStatus.OK_0, content = response });

            }
            catch (Exception ex)
            {
                Logging(_logger, LoggingEvents.Login, ex.Message, MobileHis.Enums.ResponseStatus.Error_99);
                return BadRequest();
            }

        }





Startup.cs



Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
          
            services.AddMvc();

            //services.AddDistributedMemoryCache(); 
            services.AddDistributedRedisCache(options =>
            {
                options.Configuration = "localhost:6379";
            });
            services.AddSession(options =>
            {
              
                options.Cookie.Name = "cookieName";
                options.IdleTimeout = TimeSpan.FromMinutes(5);
            });

          
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSingleton<ISessionWapper, SessionWapper>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
           
            // This session call MUST go before UseMvc()
            app.UseSession();

            //base
            app.UseMvc();
        }





我的尝试:



这是我的单元测试代码



What I have tried:

Here is my unit test code

[Fact]
       public async Task TestGetCaptcha()
       {
           ILoggerFactory f = new LoggerFactory();
           ILogger<CommonApiController> logger = f.CreateLogger<CommonApiController>();

           // Arrange
           var mockRepo = new Mock<ISessionWapper>();
           var controller = new CommonApiController(mockRepo.Object, logger);

           // Act
           var result = await controller.GetCaptcha();
           var captcha = //how to get captcha value here?
           // Assert
           var redirectToActionResult =
               Assert.IsType<RedirectToActionResult>(result);
           Assert.Equal("Home", redirectToActionResult.ControllerName);
           Assert.Equal("Index", redirectToActionResult.ActionName);
       }





或我应该嘲笑服务器?



or I should mock the server?

public class TestClientProvider : IDisposable
   {
       private TestServer _server;
       public HttpClient Client { get; private set; }

       public TestClientProvider(string baseAddress= "http://myapp.localhost:5000")
       {
          var server = new Mock<TestServer>(new WebHostBuilder().UseStartup<Startup>());
           _server = server.Object;
           //_server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
           Client = _server.CreateClient();
           Client.BaseAddress = new Uri(baseAddress);
           Client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest"); ;
       }

       public void Dispose()
       {
           _server?.Dispose();
           Client?.Dispose();
       }
   }







谢谢!




Thank you!

推荐答案

在集成测试中,您不需要获得验证码的真正价值,但在UI / Real测试中,您需要接受它,但不能从模拟框架中获取。
In integration test you do not need to get a real value of captcha but in UI /Real test you need to take it but not from mock framework.


这篇关于如何使用mock获取会话值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆