问题与单元测试嘲讽Moq
有人可以帮助我如何设置Mockobjects并验证使用Moq单元测试c#吗?
我的缓存类如下所示:
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;
}
}
我的界面是
public interface ICache
{
void Insert<T>(string cacheKey, T value);
T Get<T>(string cacheKey);
bool Exists<T>(string cacheKey);
}
我正在使用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;
}
}
我尝试了下面的模拟对象,无法得到结果。
[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
}
有人能帮我,我的数据插入缓存是正确的吗? 还帮助我如何验证单元测试Moq中的缓存数据。 我是单元测试新手,如果需要的话更正我的代码。 我无法验证,因为我正在将数据插入到实现类中的对象缓存中,但是却嘲弄了接口。 我想,如果我可以将两者联系起来,那可能是验证。 不知道,它只是我的猜测。 我很抱歉,如果这是一个愚蠢的问题,但你的帮助真的很感激。
请让我知道你是否需要进一步的细节。
此致Viswa V.
更新方案:
考虑让另一个名为“转换器”的类根据缓存中的成绩标识检索成绩名称。
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();
}
}
对于这种情况,你能告诉我如何验证? 由于此方法使用缓存来检索值,因此我不确定如何在此处使用模拟。 非常感谢您的帮助。 谢谢。
你似乎误解了嘲笑的用法。 使用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
函数中注入到类中的ICache
对象。 在这种情况下,使用Mock
将是明智的:
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.Get(It.Is<string>(cacheKey))).Return(grades);
// Test that the dependent class acts correctly according to the grades that exist in the cache
var myDependentClass = new myDependentClass(mockedObjectCache.Object);
var gradesCount = myDependentClass.CountGradesInCache();
Assert.AreEqual(6, gradesCount);
我们使用依赖类所依赖的缓存键“GradeList”来嘲笑ICache
返回6个等级。 我们现在可以测试MyDependentClass
上的方法正确返回缓存中的计数。 同样,您可以在缓存返回一个空列表或null
地方进行测试,以检查在所有情况下依赖类的行为是否正确。
在你的例子中,你想测试InMemoryCache
本身,在这种情况下你不想嘲笑任何东西。 我会简单地写这样的测试:
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.
更新的场景
对于更新的场景,不能模拟缓存,因为它是通过CacheFactory
上的静态方法检索的。 这可能是为依赖项使用依赖注入的最佳理由之一,而不是在类中自己实例化它们,而不是使用静态类/方法。
我会做什么使Converter
类可测试,将注入ICache
到类而不是使用CacheFactory
:
public class Convertor
{
private readonly ICache _cache;
public Convertor(ICache cache)
{
_cache = cache;
}
public string GetGradeName(int gradeId)
{
var gradeList = _cache.Get<List<Grade>>(CacheKeys.Grades);
return gradeList.Where(x => x.Id == gradeId).Select(x => x.Name).FirstOrDefault();
}
}
现在你可以像上面描述的那样嘲笑ICache
并测试Convertor
类的功能。
看来你对这些概念感到困惑。
如果您想(单元)测试InMemoryCache类的Insert方法,那么您定义的函数不应该模拟InMemoryCache。
Mocking适用于要测试的课程中使用的第三方课程。
事实上,你的插入方法也有一个依赖:
private readonly ObjectCache _objCache = MemoryCache.Default;
所以,你应该以某种方式模拟ObjectCache实例。
但是这次ObjectCache必须从相关接口继承以便在Moq库中使用,即IObjectCache
你应该使用:
var mockObjectCache = new Mock<IObjectCache>();
...
//Verifying:
mockObjectCache.Verify(cache => cache.Add(It.IsAny<string>())).Should().Be(true);
但是ObjectCache类是从IEnumerable和IEnumerable>继承的,所以你不能直接模拟它。 如果你真的需要模拟,你应该使用桥接口(反腐败层)。
链接地址: http://www.djcxy.com/p/35345.html上一篇: Issue with Unit test Mocking Moq
下一篇: expected result?