如何在 xUnit 和 nSubstitute 中对服务调用进行单元测试
How to unit test a service call in xUnit and nSubstitute
我一直在努力弄清楚如何对服务进行单元测试,但到目前为止一无所获。
我正在使用 xUnit 和 NSubstitute(根据朋友的建议),下面是我想要的简单测试 运行(当前失败)。
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
我的拉力赛服务 class 对数据库进行简单调用以获取所有拉力赛实体和 returns 那些:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
如有任何指导,我们将不胜感激。
我不认为单元测试构造函数带有参数是标准的。单元测试 运行ner 将更新此 class,除非您使用的是自动注入该参数的东西,否则我认为测试将失败 运行。
这是一个标准的夹具布局:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
如果您需要在测试之间进行通用设置,您可以使用无参数构造函数并在那里进行通用初始化。
就您要测试的特定 class 而言,您需要确保您的 RallyDbContext
处于已知状态以进行可重复且可靠的测试。您可能需要查找特定于测试的答案 Entity Framework 以获取更多信息。
由于您使用 .NET Core,我假设您也使用 Entity Framework Core。虽然可以模拟以前 EF 版本中的大部分操作,但 EF Core 建议使用 in-memory database 进行单元测试。 IE。您不需要模拟 RallyDbContext
,因此此特定测试不需要 NSubstitute
。在使用该服务测试控制器或应用程序时,您需要 NSubstitute
模拟该服务。
以下是您使用内存数据库编写的Test1
。
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
我的 GitHub 中有一个带有此单元测试的工作测试应用程序供您参考。我在实际应用中使用了SQL Express。
我一直在努力弄清楚如何对服务进行单元测试,但到目前为止一无所获。
我正在使用 xUnit 和 NSubstitute(根据朋友的建议),下面是我想要的简单测试 运行(当前失败)。
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
我的拉力赛服务 class 对数据库进行简单调用以获取所有拉力赛实体和 returns 那些:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
如有任何指导,我们将不胜感激。
我不认为单元测试构造函数带有参数是标准的。单元测试 运行ner 将更新此 class,除非您使用的是自动注入该参数的东西,否则我认为测试将失败 运行。
这是一个标准的夹具布局:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
如果您需要在测试之间进行通用设置,您可以使用无参数构造函数并在那里进行通用初始化。
就您要测试的特定 class 而言,您需要确保您的 RallyDbContext
处于已知状态以进行可重复且可靠的测试。您可能需要查找特定于测试的答案 Entity Framework 以获取更多信息。
由于您使用 .NET Core,我假设您也使用 Entity Framework Core。虽然可以模拟以前 EF 版本中的大部分操作,但 EF Core 建议使用 in-memory database 进行单元测试。 IE。您不需要模拟 RallyDbContext
,因此此特定测试不需要 NSubstitute
。在使用该服务测试控制器或应用程序时,您需要 NSubstitute
模拟该服务。
以下是您使用内存数据库编写的Test1
。
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
我的 GitHub 中有一个带有此单元测试的工作测试应用程序供您参考。我在实际应用中使用了SQL Express。