C# 单元测试模拟服务忽略 return
C# unit testing mocking service ignoring return
我正在编写一些单元测试来测试控制器。在那个控制器中有一个服务调用。在我的测试中,我想模拟服务调用并显然指定所需的 return.
当代码运行时,它进入控制器,当它到达服务时,我可以清楚地看到它正在使用我的模拟。但是,mock 的 return 值始终为空,而不是我指定的 return(即 expectedItem
)。有什么想法吗?
针对控制器操作的单元测试
public class SearchIATeamControllerTests : IDisposable
{
private readonly SearchIATeamController _sut;
private IFixture _fixture;
public SearchIATeamControllerTests()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_sut = _fixture.Create<SearchIATeamController>();
}
[Fact]
public async Task Get_team_name_with_ia_team_name_returns_ok()
{
// Arrange
var expectedResultItem = _fixture.Create<SearchIATeamResponse>();
var expectedItem = new List<SearchIATeamResponse>
{
expectedResultItem
};
var mockIATeamService = _fixture.Create<Mock<IIATeamSearchService>>();
mockIATeamService.Setup(m => m.GetIATeamName(It.IsAny<string>())).ReturnsAsync(expectedItem);
// Act
var result = await _sut.Get("test").ConfigureAwait(false);
}
}
为简洁起见,名称已缩写。
被测系统
public async Task<ActionResult<SearchIATeamResponse>> Get([FromQuery] string iATeamName)
{
if (iATeamName == null)
{
return BadRequest();
}
try
{
var result = await _searchIATeamService.GetIATeamName(iATeamName);
if (!result.Any())
{
return NotFound();
}
return Ok(result);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
这里的一个关键点是您正在使用 AutoFixture 创建 Mock 和服务。为了确保您在设置中使用与注入到服务中的相同的模拟实例,您可能希望在创建服务之前 Freeze
模拟实例。
public class SearchIATeamControllerTests : IDisposable
{
private readonly SearchIATeamController _sut;
private readonly Mock<IIATeamSearchService> _mockIATeamService;
private IFixture _fixture;
public SearchIATeamControllerTests()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_mockIATeamService = _fixture.Freeze<Mock<IIATeamSearchService>>();
_sut = _fixture.Create<SearchIATeamController>();
}
[Fact]
public async Task Get_team_name_with_ia_team_name_returns_ok()
{
// Arrange
var expectedResultItem = _fixture.Create<SearchIATeamResponse>();
var expectedItem = new List<SearchIATeamResponse>
{
expectedResultItem
};
_mockIATeamService.Setup(m => m.GetIATeamName(It.IsAny<string>())).ReturnsAsync(expectedItem);
// Act
var result = await _sut.Get("test").ConfigureAwait(false);
}
}
请注意,我捕获了 Freeze
的结果,因此更易于在测试方法中使用。这是我喜欢的模式,但如果您不想让另一个私有字段闲置,理论上您可以继续在您的方法中使用 _fixture.Create<>()
。
问题是由顺序引起的 - 控制器只能在模拟服务设置后声明,而不是在构造函数中声明。
我正在编写一些单元测试来测试控制器。在那个控制器中有一个服务调用。在我的测试中,我想模拟服务调用并显然指定所需的 return.
当代码运行时,它进入控制器,当它到达服务时,我可以清楚地看到它正在使用我的模拟。但是,mock 的 return 值始终为空,而不是我指定的 return(即 expectedItem
)。有什么想法吗?
针对控制器操作的单元测试
public class SearchIATeamControllerTests : IDisposable
{
private readonly SearchIATeamController _sut;
private IFixture _fixture;
public SearchIATeamControllerTests()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_sut = _fixture.Create<SearchIATeamController>();
}
[Fact]
public async Task Get_team_name_with_ia_team_name_returns_ok()
{
// Arrange
var expectedResultItem = _fixture.Create<SearchIATeamResponse>();
var expectedItem = new List<SearchIATeamResponse>
{
expectedResultItem
};
var mockIATeamService = _fixture.Create<Mock<IIATeamSearchService>>();
mockIATeamService.Setup(m => m.GetIATeamName(It.IsAny<string>())).ReturnsAsync(expectedItem);
// Act
var result = await _sut.Get("test").ConfigureAwait(false);
}
}
为简洁起见,名称已缩写。
被测系统
public async Task<ActionResult<SearchIATeamResponse>> Get([FromQuery] string iATeamName)
{
if (iATeamName == null)
{
return BadRequest();
}
try
{
var result = await _searchIATeamService.GetIATeamName(iATeamName);
if (!result.Any())
{
return NotFound();
}
return Ok(result);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
这里的一个关键点是您正在使用 AutoFixture 创建 Mock 和服务。为了确保您在设置中使用与注入到服务中的相同的模拟实例,您可能希望在创建服务之前 Freeze
模拟实例。
public class SearchIATeamControllerTests : IDisposable
{
private readonly SearchIATeamController _sut;
private readonly Mock<IIATeamSearchService> _mockIATeamService;
private IFixture _fixture;
public SearchIATeamControllerTests()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_mockIATeamService = _fixture.Freeze<Mock<IIATeamSearchService>>();
_sut = _fixture.Create<SearchIATeamController>();
}
[Fact]
public async Task Get_team_name_with_ia_team_name_returns_ok()
{
// Arrange
var expectedResultItem = _fixture.Create<SearchIATeamResponse>();
var expectedItem = new List<SearchIATeamResponse>
{
expectedResultItem
};
_mockIATeamService.Setup(m => m.GetIATeamName(It.IsAny<string>())).ReturnsAsync(expectedItem);
// Act
var result = await _sut.Get("test").ConfigureAwait(false);
}
}
请注意,我捕获了 Freeze
的结果,因此更易于在测试方法中使用。这是我喜欢的模式,但如果您不想让另一个私有字段闲置,理论上您可以继续在您的方法中使用 _fixture.Create<>()
。
问题是由顺序引起的 - 控制器只能在模拟服务设置后声明,而不是在构造函数中声明。