如何在 nunit dotnet 核心测试项目中使用 appsettings?
How to use appsettings in nunit dotnet core test project?
我已经成功地从 appsettings.json
文件中将 AppSettings 添加到我的 Api 项目中
Startup.cs 在 ConfigureServices()
函数中
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
Controller.cs
private readonly AppSettings _AppSettings;
public UserProfilesController(IOptions<AppSettings> appSettings)
{
_AppSettings = appSettings.Value;
}
但我不知道如何为我的测试项目执行此操作。我的测试项目中没有 Startup.ts
。那么如何在我的测试项目中以相同的方式添加应用程序设置呢?
编辑:
一个单元测试
[Test]
public void Post_Should_Create_A_Single_UserProfile()
{
// Arrange
var profile = Dummy.GenerateCreateUserProfileDto();
MyMvc
.Controller<UserProfilesController>()
.Calling(c => c.Post(profile))
.ShouldReturn()
.Ok()
.WithResponseModelOfType<UserProfileDto>()
.Passing(target =>
{
target.Should().NotBeNull(because: "a record is expected here");
target.Id.Should().BeGreaterThan(0, because: "a id is expected");
target.ShouldBeEquivalentTo(profile, opt => opt
.Excluding(c => c.Id)
.Excluding(c => c.CreatedOn)
.Excluding(c => c.ModifiedOn),
because: "the record returned is expected to be the same as the record inserted");
// Clean up
_Repo.Delete(target.Id);
});
}
我的post函数
[HttpPost]
public async Task<IActionResult> Post([FromBody]CreateUserProfileDto profile)
{
using (var fileManager = new FileManager())
using (var manager = new UserProfilesRepository())
{
var mapped = Mapper.Map<UserProfile>(profile);
// Only save the profile image if one is selected
if (!string.IsNullOrEmpty(profile.Image))
{
try
{
var result = fileManager.SaveProfileImage(
profile.Image,
_AppSettings.Profile.AbsolutePath,
_AppSettings.BaseUrl,
_AppSettings.Profile.RelativePath
);
mapped.FilePath = result.AbsolutePath;
mapped.ProfilePicture = result.RelativePath;
}
catch (Exception ex)
{
return StatusCode(500);
}
}
manager.Save(mapped);
return Ok(Mapper.Map<UserProfileDto>(mapped));
}
}
您正在模拟 MVC 控制器来测试它。这样,您应该创建 UserProfilesController
并传递一个模拟的 appSettings
对象。
另一种选择是启动应用程序以使用 Startup.cs
class 对其进行测试。
我从未使用过 nUnit,但在 xUnit 中我这样配置我的测试项目:
TestServer testServer = new TestServer(new WebHostBuilder().UseEnvironment("Development").UseStartup<Startup>());
由于我使用的是 Development
环境,因此我的测试项目中还需要一个 appsettings.Development.json
文件。
然后,您可以像这样使用您创建的内存服务器:
testServer.CreateClient().PostAsync(string requestUri, HttpContent content)
编辑:
TestServer 来自 Microsoft 软件包:
"Microsoft.AspNetCore.TestHost": "1.0.0"
因此,它应该可以与 nUnit 一起正常工作。
您看到的问题是使用 MyTested 模拟框架造成的。它为控制器的依赖项(IOptions<AppSettings>
实例)创建了一个具有模拟值的控制器。此模拟将为任何未专门配置的 属性 return 默认(空)值。
如果这是一个单元测试,您实际上不想通过使用 ConfigurationBuilder
等从 appsettings 加载来测试它。相反,您应该提供 AppSettings
对象作为依赖项您的测试,具有明确定义的值。
MyTested.AspNetCore.Mvc
using MyTested.AspNetCore.Mvc.DependencyInjection;
[Test]
public void Post_Should_Create_A_Single_UserProfile()
{
// Arrange
var profile = Dummy.GenerateCreateUserProfileDto();
MyMvc
.Controller<UserProfilesController>()
.WithOptions(options => options
.For<AppSettings>(settings => settings.Cache = true))
.Calling(c => c.Post(profile))
.ShouldReturn()
.Ok()
}
原答案:MyTested.WebApi
例如,您可以这样做:
using Microsoft.Extensions.Options;
[Test]
public void Post_Should_Create_A_Single_UserProfile()
{
// Arrange
var profile = Dummy.GenerateCreateUserProfileDto();
var mockedSettings = new AppSettings
{
MyValue = "the test value"
}
MyMvc
.Controller<UserProfilesController>()
.WithResolvedDependencyFor<IOptions<AppSettings>>(Options.Create(mockedSettings))
.Calling(c => c.Post(profile))
.ShouldReturn()
.Ok()
}
我已经成功地从 appsettings.json
文件中将 AppSettings 添加到我的 Api 项目中
Startup.cs 在 ConfigureServices()
函数中
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
Controller.cs
private readonly AppSettings _AppSettings;
public UserProfilesController(IOptions<AppSettings> appSettings)
{
_AppSettings = appSettings.Value;
}
但我不知道如何为我的测试项目执行此操作。我的测试项目中没有 Startup.ts
。那么如何在我的测试项目中以相同的方式添加应用程序设置呢?
编辑:
一个单元测试
[Test]
public void Post_Should_Create_A_Single_UserProfile()
{
// Arrange
var profile = Dummy.GenerateCreateUserProfileDto();
MyMvc
.Controller<UserProfilesController>()
.Calling(c => c.Post(profile))
.ShouldReturn()
.Ok()
.WithResponseModelOfType<UserProfileDto>()
.Passing(target =>
{
target.Should().NotBeNull(because: "a record is expected here");
target.Id.Should().BeGreaterThan(0, because: "a id is expected");
target.ShouldBeEquivalentTo(profile, opt => opt
.Excluding(c => c.Id)
.Excluding(c => c.CreatedOn)
.Excluding(c => c.ModifiedOn),
because: "the record returned is expected to be the same as the record inserted");
// Clean up
_Repo.Delete(target.Id);
});
}
我的post函数
[HttpPost]
public async Task<IActionResult> Post([FromBody]CreateUserProfileDto profile)
{
using (var fileManager = new FileManager())
using (var manager = new UserProfilesRepository())
{
var mapped = Mapper.Map<UserProfile>(profile);
// Only save the profile image if one is selected
if (!string.IsNullOrEmpty(profile.Image))
{
try
{
var result = fileManager.SaveProfileImage(
profile.Image,
_AppSettings.Profile.AbsolutePath,
_AppSettings.BaseUrl,
_AppSettings.Profile.RelativePath
);
mapped.FilePath = result.AbsolutePath;
mapped.ProfilePicture = result.RelativePath;
}
catch (Exception ex)
{
return StatusCode(500);
}
}
manager.Save(mapped);
return Ok(Mapper.Map<UserProfileDto>(mapped));
}
}
您正在模拟 MVC 控制器来测试它。这样,您应该创建 UserProfilesController
并传递一个模拟的 appSettings
对象。
另一种选择是启动应用程序以使用 Startup.cs
class 对其进行测试。
我从未使用过 nUnit,但在 xUnit 中我这样配置我的测试项目:
TestServer testServer = new TestServer(new WebHostBuilder().UseEnvironment("Development").UseStartup<Startup>());
由于我使用的是 Development
环境,因此我的测试项目中还需要一个 appsettings.Development.json
文件。
然后,您可以像这样使用您创建的内存服务器:
testServer.CreateClient().PostAsync(string requestUri, HttpContent content)
编辑:
TestServer 来自 Microsoft 软件包:
"Microsoft.AspNetCore.TestHost": "1.0.0"
因此,它应该可以与 nUnit 一起正常工作。
您看到的问题是使用 MyTested 模拟框架造成的。它为控制器的依赖项(IOptions<AppSettings>
实例)创建了一个具有模拟值的控制器。此模拟将为任何未专门配置的 属性 return 默认(空)值。
如果这是一个单元测试,您实际上不想通过使用 ConfigurationBuilder
等从 appsettings 加载来测试它。相反,您应该提供 AppSettings
对象作为依赖项您的测试,具有明确定义的值。
MyTested.AspNetCore.Mvc
using MyTested.AspNetCore.Mvc.DependencyInjection;
[Test]
public void Post_Should_Create_A_Single_UserProfile()
{
// Arrange
var profile = Dummy.GenerateCreateUserProfileDto();
MyMvc
.Controller<UserProfilesController>()
.WithOptions(options => options
.For<AppSettings>(settings => settings.Cache = true))
.Calling(c => c.Post(profile))
.ShouldReturn()
.Ok()
}
原答案:MyTested.WebApi
例如,您可以这样做:
using Microsoft.Extensions.Options;
[Test]
public void Post_Should_Create_A_Single_UserProfile()
{
// Arrange
var profile = Dummy.GenerateCreateUserProfileDto();
var mockedSettings = new AppSettings
{
MyValue = "the test value"
}
MyMvc
.Controller<UserProfilesController>()
.WithResolvedDependencyFor<IOptions<AppSettings>>(Options.Create(mockedSettings))
.Calling(c => c.Post(profile))
.ShouldReturn()
.Ok()
}