【问题标题】:How to set Object reference to instance of an object如何将对象引用设置为对象的实例
【发布时间】:2018-10-13 14:28:54
【问题描述】:

我正在为以下控制器编写 Xunit 测试。当我运行我的测试时,我得到了这个错误

object reference is notset to an instance of an object

这是我的测试代码

  [Fact]
    public async Task RegistrationTest()
    {
 ctrl = new AccountsControllers(context, userManager, jwtFactory, jwtoptions);
       ctrl.ModelState.AddModelError("x", "Model error");

        var mod = new RegistrationViewModel
        {
            Email = "johnmiller@sins.com"
        };
        IActionResult result = await ctrl.Register(mod);
       // Assert.Equal(mod.Email, moe);
        var viewresult = Assert.IsType<BadRequestObjectResult>(result);

    }

但是,我成功地为上下文用户管理器创建了实例

var services = new ServiceCollection();

        services.AddDbContext<ApplicationContext>(options => options
                .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Inventory;Trusted_Connection=True;ConnectRetryCount=0"));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationContext>();

        var con = new DefaultHttpContext();

        con.Features.Set<IHttpAuthenticationFeature>(new HttpAuthenticationFeature());

        services.AddSingleton<IHttpContextAccessor>(h => new HttpContextAccessor { HttpContext = con });

var serviceProvider = services.BuildServiceProvider();

        context = serviceProvider.GetRequiredService<ApplicationContext>();
        userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();

我不知道如何为 IJwtFactory 和 JwtIssuerOptions 创建

这是我的 Accounts 控制器构造函数

 public AccountsControllers(ApplicationContext context, UserManager<ApplicationUser> userManager, 
            IJwtFactory jwtFactory, IOptions<JwtIssuerOptions> jwtoptions)
    {
        appDbContext = context;

        this.userManager = userManager;
        this.jwtFactory = jwtFactory;
        jwtOptions = jwtoptions.Value;

        serializerSettings = new JsonSerializerSettings
        {
            Formatting = Formatting.Indented
        };
    }

这是帐户控制器中的登录方法

 public async Task<IActionResult> Login([FromBody]LoginViewModel credentials)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }


        var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);

        if (identity == null)
        {
            return BadRequest(Errors.AddErrorToModelState("login_failure", "Invalid username or password.", ModelState));
        }
        var response = new
        {
            id = identity.Claims.Single(c => c.Type == "id").Value,
           auth_token = await jwtFactory.GenerateEncodedToken(credentials.UserName, identity),
            expires_in = (int)jwtOptions.ValidFor.TotalSeconds
        };

        var json = JsonConvert.SerializeObject(response, serializerSettings);
        return new OkObjectResult(json);
    }

声明身份

    public async Task<ClaimsIdentity> GetClaimsIdentity(string userName, string password)
    {

        if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
        {
            // get the user to verifty
            var userToVerify = await userManager.FindByNameAsync(userName);


            if (userToVerify != null)
            {

                // check the credentials  
              if (await userManager.CheckPasswordAsync(userToVerify, password))
               {
                   return await Task.FromResult(jwtFactory.GenerateClaimsIdentity(userName, userToVerify.Id));
                }

            }

        }

        return await Task.FromResult<ClaimsIdentity>(null);
    }

【问题讨论】:

    标签: asp.net-core-mvc jwt claims-based-identity xunit xunit.net


    【解决方案1】:

    问题是您试图模拟出所有的依赖项,而您显然在某处遗漏了一些东西。每当您发现自己需要模拟多个依赖项时,这都是您处于集成测试领域的一个非常明显的迹象。

    一般来说,任何时候您在测试控制器操作时,都是在进行集成测试。尽管它们看起来类似于类中的方法,但作为请求管道的一部分需要发生很多事情才能真正使它们正常运行,如果没有实际请求,您无法真正测试它们。特别是,诸如使用经过身份验证的用户创建HttpContext 之类的事情不会发生在请求管道之外。您也可以在技术上模拟所有这些,但同样,这只是您必须手动提供的更多依赖项,以及创建失败的测试的更多机会,因为设置不正确,而不是因为任何事情实际上都错误。

    既然如此,请实际进行真正的集成测试并使用TestServer。您可以将Startup 类提供给它,以便所有服务都按应有的方式注册和注入,然后您只需发出请求并验证响应对象。为了模拟数据库连接之类的东西,您应该设置一个“测试”环境并在 Startup.cs 中配置它以使用内存中 EF 数据库提供程序之类的东西。然后,您可以指定您的TestServer 应该使用那个“测试”环境,然后您就可以开始了。请参阅documentation 了解更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      相关资源
      最近更新 更多