为什么我的模拟设定是空的? [英] Why is my mock set empty?

查看:150
本文介绍了为什么我的模拟设定是空的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始学习单元测试和嘲弄。我花了一整天阅读不同的教程,试图找到与实践最好的之一。我已经在测试与模拟框架(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 of data.

What is going on here? Shouldn't that code insert a blog record into the data object, and thus pulling it when calling GetAllBlogs()? 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 your data 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 your DbSet (preferrably via call to service) configured version of Add 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 of list 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 via GetAllBlogs method but rather by verification on the mock itself:

mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());

这篇关于为什么我的模拟设定是空的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆