如何使用Moq单元测试C#设置Mockobjects并进行验证?
我的缓存类如下所示:如何使用Moq单元测试C#设置Mockobjects并进行验证?,c#,asp.net-mvc,dependency-injection,moq,memorycache,C#,Asp.net Mvc,Dependency Injection,Moq,Memorycache,我的缓存类如下所示: public class InMemoryCache : ICache { private readonly ObjectCache _objCache = MemoryCache.Default; public void Insert<T>(string cacheKey, T value) { _objCache.Add(cacheKey, value, DateTimeOffset.MaxValue)
public class InMemoryCache : ICache
{
private readonly ObjectCache _objCache = MemoryCache.Default;
public void Insert<T>(string cacheKey, T value)
{
_objCache.Add(cacheKey, value, DateTimeOffset.MaxValue);
}
public T Get<T>(string cacheKey)
{
if (cacheKey != null)
return (T)Convert.ChangeType(_objCache.Get(cacheKey), typeof(T));
else
return default(T);
}
public bool Exists<T>(string cacheKey)
{
return _objCache.Get(cacheKey) != null;
}
}
内存缓存中的公共类:ICache
{
私有只读对象缓存_objCache=MemoryCache.Default;
公共void插入(字符串缓存键,T值)
{
_Add(cacheKey,value,DateTimeOffset.MaxValue);
}
公共T获取(字符串缓存键)
{
if(cacheKey!=null)
return(T)Convert.ChangeType(_objCache.Get(cacheKey),typeof(T));
其他的
返回默认值(T);
}
公共bool存在(字符串cacheKey)
{
return _objCache.Get(cacheKey)!=null;
}
}
我的界面是
public interface ICache
{
void Insert<T>(string cacheKey, T value);
T Get<T>(string cacheKey);
bool Exists<T>(string cacheKey);
}
公共接口ICache
{
无效插入(字符串缓存键,T值);
T Get(字符串缓存键);
bool存在(字符串缓存键);
}
我正在使用CacheFactory调用InMemoryCache类:
public class CacheFactory
{
public static ICache Cache { get; set; }
public static void Insert<T>(string cacheKey, T value)
{
Cache.Insert<T>(cacheKey, value);
}
public static T Get<T>(string cacheKey)
{
return Cache.Get<T>(cacheKey);
}
public static bool Exists<T>(string cacheKey)
{
return Cache.Get<T>(cacheKey) != null;
}
}
公共类缓存工厂
{
公共静态ICache缓存{get;set;}
公共静态void插入(字符串缓存键,T值)
{
Cache.Insert(cacheKey,value);
}
公共静态T Get(字符串缓存键)
{
返回Cache.Get(cacheKey);
}
存在公共静态bool(字符串cacheKey)
{
返回Cache.Get(cacheKey)!=null;
}
}
我尝试了下面这样的模拟对象,但无法得到结果
[Fact()]
public void CacheManager_Insert_Test()
{
string cacheKey = "GradeList";
Mock<ICache> mockObject = new Mock<ICache>();
List<Grade> grades = new List<Grade>
{
new Grade() {Id = 1, Name = "A*"},
new Grade() {Id = 2, Name = "A"},
new Grade() {Id = 3, Name = "B"},
new Grade() {Id = 4, Name = "C"},
new Grade() {Id = 5, Name = "D"},
new Grade() {Id = 6, Name = "E"}
};
var mockedObjectCache = new Mock<ICache>();
// Setup mock's Set method
mockedObjectCache.Setup(m => m.Insert(cacheKey, grades));
// How to get the Mocked data and verify it here
}
[Fact()]
public void CacheManager_Insert_Test()
{
string cacheKey=“成绩表”;
Mock mockObject=new Mock();
列表等级=新列表
{
新等级(){Id=1,Name=“A*”},
新等级(){Id=2,Name=“A”},
新等级(){Id=3,Name=“B”},
新等级(){Id=4,Name=“C”},
新等级(){Id=5,Name=“D”},
新等级(){Id=6,Name=“E”}
};
var mockedObjectCache=new Mock();
//设置mock的Set方法
mockedObjectCache.Setup(m=>m.Insert(cacheKey,grades));
//如何获取模拟数据并在此处进行验证
}
有人能检查一下我插入缓存的数据是否正确吗?另外,如何在单元测试Moq中验证缓存数据?我不熟悉单元测试
我无法验证,因为我正在将数据插入到实现类中的对象缓存中,但正在模拟接口。我想如果我能把两者都联系起来,那可能是在验证。不确定,这只是我的猜测
更新的场景
考虑使用另一个名为“Convertor”的类,该类根据缓存中的等级ID检索等级名称
public class Convertor
{
// Gets Grade ID and Displays Grade Name
public string GetGradeName(int gradeId)
{
var gradeList = CacheFactory.Cache.Get<List<Grade>>(CacheKeys.Grades);
return gradeList.Where(x => x.Id == gradeId).Select(x => x.Name).FirstOrDefault();
}
}
公共类转换器
{
//获取等级ID并显示等级名称
公共字符串GetGradeName(int gradeId)
{
var gradeList=CacheFactory.Cache.Get(CacheKeys.Grades);
返回gradeList.Where(x=>x.Id==gradeId)。选择(x=>x.Name)。FirstOrDefault();
}
}
对于这种情况,我如何验证这一点?由于此方法使用缓存来检索值,因此我不确定如何在此处使用mock。您似乎误解了mock的用法。使用mock的原因是测试依赖类而不必担心依赖性 假设您有以下课程:
public class MyDependentClass {
private readonly ICache _cache;
public MyDependentClass(ICache cache)
{
_cache = cache;
}
public int CountGradesInCache()
{
// Behavior depends on what's in the _cache object
return _cache.Get<List<Grade>>("GradeList").Count;
}
}
我们模拟ICache
,使用依赖类所依赖的缓存键“GradeList”返回6个等级。我们现在可以测试MyDependentClass
上的方法是否正确返回缓存中的计数。同样,您可以在缓存返回空列表或null
的情况下进行测试,以检查依赖类的行为在所有情况下是否正确
在您的示例中,似乎要测试内存缓存中的本身,在这种情况下,您不想模拟任何东西。我只需编写如下测试:
var cache = new InMemoryCache();
var list = new List<Grade> { ... };
var cache.Insert("GradeList", list);
var cachedList = cache.Get<List<Grade>>("GradeList");
// Assert that the list retrieved from cache has the expected values.
现在,您可以模拟ICache
并测试转换器的功能,就像我上面描述的那样。您似乎误解了模拟的用法。使用mock的原因是测试依赖类而不必担心依赖性
假设您有以下课程:
public class MyDependentClass {
private readonly ICache _cache;
public MyDependentClass(ICache cache)
{
_cache = cache;
}
public int CountGradesInCache()
{
// Behavior depends on what's in the _cache object
return _cache.Get<List<Grade>>("GradeList").Count;
}
}
我们模拟ICache
,使用依赖类所依赖的缓存键“GradeList”返回6个等级。我们现在可以测试MyDependentClass
上的方法是否正确返回缓存中的计数。同样,您可以在缓存返回空列表或null
的情况下进行测试,以检查依赖类的行为在所有情况下是否正确
在您的示例中,似乎要测试内存缓存中的本身,在这种情况下,您不想模拟任何东西。我只需编写如下测试:
var cache = new InMemoryCache();
var list = new List<Grade> { ... };
var cache.Insert("GradeList", list);
var cachedList = cache.Get<List<Grade>>("GradeList");
// Assert that the list retrieved from cache has the expected values.
现在,您可以模拟ICache
并测试转换器的功能,就像我上面描述的那样。您似乎对这些概念感到困惑
如果您想(单元)测试InMemoryCache类的Insert方法,您肯定不应该模拟InMemoryCache
模拟用于您要测试的类中使用的第三方类
事实上,您的insert方法中还有一个依赖项:
private readonly ObjectCache _objCache = MemoryCache.Default;
因此,您应该以某种方式模拟ObjectCache实例
但这次ObjectCache必须从相关接口继承,以便在Moq库中使用,即IOObjectCache
你应该使用:
var mockObjectCache = new Mock<IObjectCache>();
...
//Verifying:
mockObjectCache.Verify(cache => cache.Add(It.IsAny<string>())).Should().Be(true);
var mockObjectCache=new Mock();
...
//验证:
mockObjectCache.Verify(cache=>cache.Add(It.IsAny()).Should().Be(true);
然而,ObjectCache类是从IEnumerable和IEnumerable>继承的,所以您不能直接模拟它。如果您真的需要模拟,您应该使用桥接接口(反腐败层)。您似乎对这些概念感到困惑
如果您想(单元)测试InMemoryCache类的Insert方法,您肯定不应该模拟InMemoryCache
模拟用于您要测试的类中使用的第三方类
事实上你有一个