起订量功能参数
Moq Func Parameter
我有一个使用 Func 参数的单元测试,我似乎无法使用 MOQ。查看 Whosebug 上 Func 参数的其他示例,这是我认为应该起作用的:
要测试的代码:
public class PatternManager : IPatternManager
{
private readonly ICacheManager _cacheManager;
private readonly IDataRepo _data;
public PatternManager(ICacheManager cacheManager, IDataRepo dataRepo)
{
_cacheManager = cacheManager;
_data = dataRepo;
}
public List<Pattern> GetAllPatterns()
{
var allPatterns = _cacheManager.Get(() => _data.GetAllPatterns(), nameof(_data.GetAllPatterns));
return allPatterns;
}
public Pattern GetBestPattern(int[] ids)
{
var patternList = GetAllPatterns().Where(w => w.PatternId > 1);
... More code...
}
...
}
public interface ICacheManager
{
T Get<T>(Func<T> GetMethodIfNotCached, string cacheName = null, int? cacheDurationInSeconds = null, string cachePath = null);
}
我得到的不是我期望从 GetAllPatterns() 获得的模式列表,而是空值。
[Test]
public void PatternManager_GetBestPattern()
{
var cacheManager = new Mock<ICacheManager>();
var dataRepo = new Mock<IDataRepo>();
dataRepo.Setup(d => d.GetAllPatterns())
.Returns(GetPatternList());
cacheManager.Setup(s => s.Get(It.IsAny<Func<List<Pattern>>>(), "", 100, "")) // Has optional params
.Returns(dataRepo.Object.GetAllPatterns());
patternManager = new PatternManager(cacheManager.Object, dataRepo.Object);
int[] pattern = { 1, 2, 3};
var bestPattern = patternManager.GetBestPattern(pattern);
Assert.AreEqual(1, bestPattern.PatternId);
}
private static List<Pattern> GetPatternList()
{
... returns a list of Pattern
}
这个设置有什么问题?
默认情况下,模拟返回 null,因为设置与调用模拟成员时实际传递的设置不同。
看看被测成员中调用了什么
//...
var allPatterns = _cacheManager.Get(() => _data.GetAllPatterns(), nameof(_data.GetAllPatterns));
//...
这很可能是 Func<List<Pattern>>
和字符串 "GetAllPatterns"
,其他可选参数默认为可选默认值。
现在看看测试中设置了什么
//...
cacheManager
.Setup(s => s.Get(It.IsAny<Func<List<Pattern>>>(), "", 100, "")) // Has optional params
.Returns(dataRepo.Object.GetAllPatterns());
//...
空字符串和实际的 int
值被设置为预期的值,但这不是被测成员实际调用的值。
模拟因此不知道如何处理执行测试时传递的实际值,因此默认为 null.
使用 It.IsAny<>
重构设置以接受各个参数的任何值
//...
cacheManager
.Setup(s => s.Get<List<Pattern>>(It.IsAny<Func<List<Pattern>>>(), It.IsAny<string>(), It.IsAny<int?>(), It.IsAny<string>()))
.Returns((Func<List<Pattern>> f, string cn, int? cd, string cp) => f()); //Invokes function and returns result
//...
并注意使用委托来捕获 Returns
中的参数。这样就可以像在被测成员中那样调用实际函数。
我有一个使用 Func 参数的单元测试,我似乎无法使用 MOQ。查看 Whosebug 上 Func 参数的其他示例,这是我认为应该起作用的:
要测试的代码:
public class PatternManager : IPatternManager
{
private readonly ICacheManager _cacheManager;
private readonly IDataRepo _data;
public PatternManager(ICacheManager cacheManager, IDataRepo dataRepo)
{
_cacheManager = cacheManager;
_data = dataRepo;
}
public List<Pattern> GetAllPatterns()
{
var allPatterns = _cacheManager.Get(() => _data.GetAllPatterns(), nameof(_data.GetAllPatterns));
return allPatterns;
}
public Pattern GetBestPattern(int[] ids)
{
var patternList = GetAllPatterns().Where(w => w.PatternId > 1);
... More code...
}
...
}
public interface ICacheManager
{
T Get<T>(Func<T> GetMethodIfNotCached, string cacheName = null, int? cacheDurationInSeconds = null, string cachePath = null);
}
我得到的不是我期望从 GetAllPatterns() 获得的模式列表,而是空值。
[Test]
public void PatternManager_GetBestPattern()
{
var cacheManager = new Mock<ICacheManager>();
var dataRepo = new Mock<IDataRepo>();
dataRepo.Setup(d => d.GetAllPatterns())
.Returns(GetPatternList());
cacheManager.Setup(s => s.Get(It.IsAny<Func<List<Pattern>>>(), "", 100, "")) // Has optional params
.Returns(dataRepo.Object.GetAllPatterns());
patternManager = new PatternManager(cacheManager.Object, dataRepo.Object);
int[] pattern = { 1, 2, 3};
var bestPattern = patternManager.GetBestPattern(pattern);
Assert.AreEqual(1, bestPattern.PatternId);
}
private static List<Pattern> GetPatternList()
{
... returns a list of Pattern
}
这个设置有什么问题?
默认情况下,模拟返回 null,因为设置与调用模拟成员时实际传递的设置不同。
看看被测成员中调用了什么
//...
var allPatterns = _cacheManager.Get(() => _data.GetAllPatterns(), nameof(_data.GetAllPatterns));
//...
这很可能是 Func<List<Pattern>>
和字符串 "GetAllPatterns"
,其他可选参数默认为可选默认值。
现在看看测试中设置了什么
//...
cacheManager
.Setup(s => s.Get(It.IsAny<Func<List<Pattern>>>(), "", 100, "")) // Has optional params
.Returns(dataRepo.Object.GetAllPatterns());
//...
空字符串和实际的 int
值被设置为预期的值,但这不是被测成员实际调用的值。
模拟因此不知道如何处理执行测试时传递的实际值,因此默认为 null.
使用 It.IsAny<>
//...
cacheManager
.Setup(s => s.Get<List<Pattern>>(It.IsAny<Func<List<Pattern>>>(), It.IsAny<string>(), It.IsAny<int?>(), It.IsAny<string>()))
.Returns((Func<List<Pattern>> f, string cn, int? cd, string cp) => f()); //Invokes function and returns result
//...
并注意使用委托来捕获 Returns
中的参数。这样就可以像在被测成员中那样调用实际函数。