为什么我的模拟设定是空的? [英] Why is my mock set empty?
问题描述
我刚开始学习单元测试和嘲弄。我花了一整天阅读不同的教程,试图找到与实践最好的之一。我已经在测试与模拟框架(EF6起)作为它使用EF6(现代),以及什么似乎是一个非常流行的模拟框架(MOQ)。此外,它是相当香草和在MSDN webset主办。它必须是体面的,对吧?
我已经成立了一个项目,正是因为在这个例子中指定并正在运行通过测试的例子调试,以确保我的理解到底是怎么回事。我通过工作测试如下:
[TestClass中]
公共类QueryTests
{
[TestMethod的]
公共无效GetAllBlogs_orders_by_name()
{
VAR数据=新的List<博客>
{
新博客{名称=BBB},
新博客{名称=ZZZ},
新博客{名称=AAA},
} .AsQueryable();
变种mockSet =新的模拟< DbSet<博客>>();
mockSet.As<&IQueryable的LT;博客>方式>()设置(M => m.Provider).Returns(data.Provider);
mockSet.As<&IQueryable的LT;博客>方式>()设置(M => m.Expression).Returns(data.Expression);
mockSet.As<&IQueryable的LT;博客>方式>()设置(M => m.ElementType).Returns(data.ElementType);
mockSet.As<&IQueryable的LT;博客>方式>()设置。(M => m.GetEnumerator())返回(data.GetEnumerator());
变种mockContext =新的模拟< BloggingContext>();
mockContext.Setup(C => c.Blogs).Returns(mockSet.Object);
VAR的服务=新BlogService(mockContext.Object);这里
//测试代码
变种博客= service.GetAllBlogs();
Assert.AreEqual(3 blogs.Count);
Assert.AreEqual(AAA,博客[0] .Name点);
Assert.AreEqual(BBB,博客[1] .Name点);
Assert.AreEqual(ZZZ,博客[2] .Name点);
}
}
这是非常简单的,我率先相信我理解单元测试和嘲讽的框架。凉!我决定通过插入 service.AddBlog(ADO.NET博客来进行实验,以验证自己,http://blogs.msdn.com/adonet\");
(从以前的例子)入上述TestMethod的,服务实例化之后。
我希望我过去步 VAR博客= service.GetAllBlogs();
,博客应包含新条目,但它没有。它仅包含3从数据
。
的初始化
这是怎么回事?这难道不该代码中插入一个博客记录到数据
对象,从而调用 GetAllBlogs当拉()
?也许我不理解嘲笑的想法是否正确?
为什么我的模拟设定是空的?
块引用>
由于未配置(的设置的),它当您插入数据,将其采取任何行动。当创建一个模拟它失去所有在场的原班和标记
虚拟
的逻辑。起订量简单地覆盖这些方法,这样以后就可以配置它们做任何事情(返回值,扔等)。
当然,你可以设置
添加
方法插入数据返回到您的数据
博客列表:VAR mockSet =新的模拟< DbSet<博客>>();
mockSet.Setup(M = GT; m.Add< It.IsAny<博客>())。回调(博客=> data.Add(博客));
在
添加
方法将在调用你的DbSet
(最好是通过调用服务)的配置的版本添加
将接管并插入博客对您的数据列表(回调
方法告知起订量来的调用此代码的时候嘲笑方法被调用)。
您也可以设法防止
硬道理通过的 /快速入门#定制,模拟行为相对=nofollow> CallBase 参数。但是,这也可能无法工作的DbSet不知道
列表
的存在,你就极有可能更多地配置即可。
在最后要注意,一旦你的实验结晶,你应该认识到,在配置
添加
不会是必要的,因为你不会被检查博客是否:通过
GetAllBlogs
方法,而是通过验证的模拟本身添加mockSet.Verify(M = GT; m.Add(It.IsAny<博客>()),Times.Once());
I am just starting to learn about unit testing and mocking. I've spent all day reading different tutorials, trying to find the best one to practice with. I've settled on Testing with a mocking framework (EF6 onwards) as it is using EF6 (modern), as well as what seems to be a very popular mocking framework (Moq). Also, it is quite vanilla and hosted on the MSDN webset. It has to be decent, right?
I've set up a project exactly as specified in the example and am running the debugger through the test examples to make sure I understand what is going on. The test I'm working through is as follows:
[TestClass] public class QueryTests { [TestMethod] public void GetAllBlogs_orders_by_name() { var data = new List<Blog> { new Blog { Name = "BBB" }, new Blog { Name = "ZZZ" }, new Blog { Name = "AAA" }, }.AsQueryable(); var mockSet = new Mock<DbSet<Blog>>(); mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider); mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression); mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType); mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); var mockContext = new Mock<BloggingContext>(); mockContext.Setup(c => c.Blogs).Returns(mockSet.Object); var service = new BlogService(mockContext.Object); //test code here var blogs = service.GetAllBlogs(); Assert.AreEqual(3, blogs.Count); Assert.AreEqual("AAA", blogs[0].Name); Assert.AreEqual("BBB", blogs[1].Name); Assert.AreEqual("ZZZ", blogs[2].Name); } }
It is very simple and I am lead to believe that I am understanding unit testing and the mocking framework. Cool! I decide to perform an experiment to validate myself, by inserting
service.AddBlog("ADO.NET Blog", "http://blogs.msdn.com/adonet");
(from a previous example) into the above TestMethod, just after the service is instantiated.I expect that as I step past
var blogs = service.GetAllBlogs();
, blogs should contain my new entry, but it does not. It only contains the 3 from the initialization ofdata
.What is going on here? Shouldn't that code insert a blog record into the
data
object, and thus pulling it when callingGetAllBlogs()
? Perhaps I am not understanding the idea of mocks properly?解决方案Why is my mock set empty?
Because you didn't configure (setup) it to take any action when you insert data to it. When a mock is created it "loses" all the logic that was present on the original class and marked
virtual
. Moq simply overrides such methods so that later you can configure them to do anything (return value, throw, etc).Naturally, you can setup
Add
method to insert data back to yourdata
blog list:var mockSet = new Mock<DbSet<Blog>>(); mockSet.Setup(m => m.Add<It.IsAny<Blog>()).Callback(blog => data.Add(blog));
When
Add
method will be invoked on yourDbSet
(preferrably via call to service) configured version ofAdd
will take over and insert blog to your data list (Callback
method tells Moq to "invoke this code" when mocked method is called).You could also try to prevent overriding of
Add
by using CallBase parameter. However, this might not work as your DbSet is not aware oflist
existence, you'll most likely have to configure it more heavily then.On a final note, once your experiment crystallizes you should realize that configuring
Add
won't be necessary because you won't be checking whether blog was added viaGetAllBlogs
method but rather by verification on the mock itself:mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
这篇关于为什么我的模拟设定是空的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!