Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Moq验证列表类型的参数<>;?_C#_Moq - Fatal编程技术网

C# 使用Moq验证列表类型的参数<>;?

C# 使用Moq验证列表类型的参数<>;?,c#,moq,C#,Moq,使用Moq,我希望能够验证传递给模拟方法调用的参数是否满足某些条件。在这个场景中,我想检查传入模拟方法的列表是否具有一定的大小: var mockSomeRepository = new Mock<SomeRepository>(); mockSomeRepository.Setup(m => m.Write(It.IsAny<List<SomeDTO>>())).Verifiable(); var mainClass = new MainClass(

使用Moq,我希望能够验证传递给模拟方法调用的参数是否满足某些条件。在这个场景中,我想检查传入模拟方法的列表是否具有一定的大小:

var mockSomeRepository = new Mock<SomeRepository>();
mockSomeRepository.Setup(m => m.Write(It.IsAny<List<SomeDTO>>())).Verifiable();

var mainClass = new MainClass(mockSomeRepository.Object);
List<SomeDTO> someList = GetListWith25Items();

mainClass.DoRepositoryWrite(someList); // calls SomeRepository.Write(someList);

mockSomeRepository.Verify(m => 
    m.Write(It.Is<List<SomeDTO>>(l => l.Count() == 25)), Times.Once());
var mockSomeRepository=new Mock();
mockSomeRepository.Setup(m=>m.Write(It.IsAny()).Verifiable();
var mainClass=新的mainClass(mockSomeRepository.Object);
List someList=GetListWith25项();
mainClass.DoRepositoryWrite(someList);//调用SomeRepository.Write(someList);
mockSomeRepository.Verify(m=>
m、 写(It.Is(l=>l.Count()==25)),乘以.Once();

verify断言抛出一个异常,表示该方法从未以这种方式调用。但是,删除约束并使用
Is.Any()
会导致通过。我不确定我在这里是否正确地使用了它。Is()——这是我直觉上希望我的测试看起来的样子,但我不确定我是否正确地使用了框架。我应该如何正确地构建此测试?

您可以取消对模拟的设置和可验证调用。只需使用验证

我创建了一个小测试项目,这对我很有用:

using System;
using System.Collections.Generic;
using System.Linq;
using Moq;

namespace csharp
{
    public class SomeDTO { }

    public class SomeRepository { public virtual void Write(List<SomeDTO> list) { } }

    public class MainClass
    {
        private SomeRepository someRepository;

        public MainClass(SomeRepository someRepository) { this.someRepository = someRepository; }

        public void DoRepositoryWrite(List<SomeDTO> list) { this.someRepository.Write(list); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var mockSomeRepository = new Mock<SomeRepository>();
            var someList = Enumerable.Repeat(new SomeDTO(), 25).ToList();

            var mainClass = new MainClass(mockSomeRepository.Object);
            mainClass.DoRepositoryWrite(someList);

            mockSomeRepository.Verify(m => m.Write(It.IsAny<List<SomeDTO>>()), Times.Once(), "Write was not called");
            mockSomeRepository.Verify(m => m.Write(It.Is<List<SomeDTO>>(l => l.Count == 25)), Times.Once(), "Write was not called with a 25-element-list");
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用最小起订量;
命名空间csharp
{
公共类SomeDTO{}
公共类SomeRepository{public virtual void Write(List){}
公共类主类
{
私有存储库;
公共MainClass(SomeRepository SomeRepository){this.SomeRepository=SomeRepository;}
public void DoRepositoryWrite(List){this.someRepository.Write(List);}
}
班级计划
{
静态void Main(字符串[]参数)
{
var mockSomeRepository=new Mock();
var someList=Enumerable.Repeat(new SomeDTO(),25.ToList();
var mainClass=新的mainClass(mockSomeRepository.Object);
mainClass.DoRepositoryWrite(someList);
mockSomeRepository.Verify(m=>m.Write(It.IsAny()),Times.Once(),“未调用Write”);
mockSomeRepository.Verify(m=>m.Write(It.Is(l=>l.Count==25)),Times.Once(),“Write未使用25个元素列表调用”);
}
}
}

当我发布这个问题时,我遗漏了一些重要的细节。我想详细说明实际发生了什么,以防将来对某人有所帮助。我的测试方法实际上是清除传递给模拟的列表:

public class SomeDTO { }

public class SomeRepository
{
    public virtual void Write(IEnumerable<SomeDTO> list) { }
}

public class MainClass
{
    private readonly SomeRepository _someRepository;
    private readonly List<SomeDTO> _testList = new List<SomeDTO>(); 

    public MainClass(SomeRepository someRepository)
    {
        _someRepository = someRepository;
    }

    public void DoRepositoryWrite()
    {
        _testList.AddRange(Enumerable.Repeat(new SomeDTO(), 25));
        _someRepository.Write(_testList);
        _testList.Clear();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var mockSomeRepository = new Mock<SomeRepository>();

        var mainClass = new MainClass(mockSomeRepository.Object);

        mainClass.DoRepositoryWrite();

        mockSomeRepository.Verify(m => m.Write(It.IsAny<IEnumerable<SomeDTO>>()), Times.Once(), "Write was not called");
        mockSomeRepository.Verify(m => m.Write(It.Is<IEnumerable<SomeDTO>>(l => l.Count() == 25)), Times.Once(), "Write was not called with a 25-element-list");
    }
}
公共类SomeDTO{}
公共类存储库
{
公共虚拟空写(IEnumerable list){}
}
公共类主类
{
私有只读SomeRepository\u SomeRepository;
私有只读列表_testList=new List();
公共MainClass(SomeRepository SomeRepository)
{
_someRepository=someRepository;
}
公共无效DoRepositoryWrite()
{
_AddRange(Enumerable.Repeat(newsomedto(),25));
_someRepository.Write(_testList);
_testList.Clear();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var mockSomeRepository=new Mock();
var mainClass=新的mainClass(mockSomeRepository.Object);
mainClass.DoRepositoryWrite();
mockSomeRepository.Verify(m=>m.Write(It.IsAny()),Times.Once(),“未调用Write”);
mockSomeRepository.Verify(m=>m.Write(It.Is(l=>l.Count()==25)),Times.Once(),“Write未使用25个元素列表调用”);
}
}
回过头来看,这似乎有点明显,但对我来说,这里的收获是mock保留了对它所传递的列表的引用。因此,您需要小心任何会改变列表的副作用

为了正确地编写测试,我需要在调用mock方法时立即检查传递列表的属性。为此,我使用了回调:

int listCountAtTimeOfCall = 0;
mockSomeRepository.Setup(
    m => m.Write(It.IsAny<IEnumerable<SomeDTO>>())).Callback
        <IEnumerable<SomeDTO>>(list => listCountAtTimeOfCall = list.Count());

... do the work ...

Assert.AreEqual(listCountAtTimeOfCall, 25);
int-listCountAtTimeOfCall=0;
mockSomeRepository.Setup(
m=>m.Write(It.IsAny()).Callback
(list=>listCountAtTimeOfCall=list.Count());
... 做这项工作。。。
Assert.AreEqual(ListCountAttimeCall,25);

删除对安装程序的调用会给我带来一个不同的错误:预期对模拟调用一次,但为0次:m=>m.Write(It.Is(l=>l.Count()==25))未配置任何设置。可能您的单元测试是正确的,但您的MainClass.DoRepositoryWrite-method不是?在抛出的MockException中是否列出了任何“已执行的调用”?如果没有,那么mainClass从未调用过SomeRepository.Write。这被证明是正确的,测试实际上工作正常。谢谢你的帮助!我有过好几次这样的问题。我为一个现有方法编写了一个测试,测试一次又一次失败。寻找测试中的bug,我意识到方法被破坏了,而不是测试:-),这就是为什么应该使用TDD:p