我有一个具有以下实现的类:
public sealed class HotelRepository : IHotelRepository
{
private readonly string _dataSource;
public HotelRepository(string dataSource) => _dataSource = dataSource;
/// <inheritdoc />
public async Task<IEnumerable<Hotel>> GetAllAsync() =>
await Task.Run(() => JObject.Parse(File.ReadAllText(_dataSource))["hotels"].ToList().Select(x => x.ToObject<Hotel>()));
/// <inheritdoc />
public async Task<IEnumerable<Hotel>> GetListByMatchAsync(string name) =>
await GetAllAsync().ContinueWith(x => x.Result.Where(y => y.Name.Contains(name, StringComparison.CurrentCultureIgnoreCase)));
}
如您所见,GetListByMatchAsync
方法调用GetAllAsync
,然后在返回结果之前执行一些逻辑。
当我尝试对该存储库进行模拟以进行单元测试时,我一直在努力从GetListByMatchAsync
中获取结果,因为它总是作为空引用异常而失败。
这是单元测试:
[TestCase("Test", "X")]
[TestCase("Hotel", "X")]
[TestCase("Name", "X")]
public async Task GetListByMatchAsync_GetHotelListByMatchingNameAsync_ReturnsFiveMatchingHotels(string name, string nonMatch)
{
_hotelRepositoryMock = new Mock<IHotelRepository>();
_hotelRepository = _hotelRepositoryMock.Object;
// Set up sample data.
var data = new List<Hotel>
{
new Hotel{Id = 1, Name = $"{name}", Description = "Description2", Location = "Location2", Rating = Rating.Two},
new Hotel{Id = 2, Name = $"{name.ToUpper()}", Description = "Description1", Location = "Location1", Rating = Rating.Five},
new Hotel{Id = 3, Name = $"{name.ToLower()}", Description = "Description2", Location = "Location2", Rating = Rating.Three},
new Hotel{Id = 4, Name = $"{name} {nonMatch}", Description = "Description2", Location = "Location2", Rating = Rating.One},
new Hotel{Id = 5, Name = nonMatch, Description = "Description2", Location = "Location2", Rating = Rating.One},
};
// Set up mock methods and ensure these method returns any sample data.
_hotelRepositoryMock.Setup(x => x.GetListByMatchAsync(It.IsAny<string>()));
_hotelRepositoryMock.Setup(x => x.GetAllAsync()).ReturnsAsync(data);
var result = await _hotelRepository.GetListByMatchAsync(name);
// Cast to list to make assertions.
var hotels = result.ToList();
Assert.That(hotels, Is.TypeOf<List<Hotel>>());
Assert.That(hotels.Count, Is.EqualTo(4));
}
如何使此测试有效,以使GetListByMatchAsync
模拟方法在调用模拟的GetAllAsync
方法之后进行一些逻辑处理?
答案 0 :(得分:2)
首先,您显示的代码可能无法工作,因为您尝试设置的方法不是虚拟的。将要Setup
的方法声明为virtual
。
第二,这是错误的:
_hotelRepositoryMock.Setup(x => x.GetListByMatchAsync(It.IsAny<string>()));
通过此调用,您可以有效地设置GetListByMatchAsync
来返回default(Task<IEnumerable<Hotel>>)
,即null
。那显然不是您想要的。要么:
.Returns(...)
指定方法应返回的内容;或者,.CallBase()
。 (这可能是您所需要的。)