【问题标题】:Use moq to mock a type with generic parameter使用 moq 模拟具有泛型参数的类型
【发布时间】:2026-01-28 13:15:01
【问题描述】:

我有以下接口。由于 T 是通用的,我不确定如何使用 Moq 来模拟 IRepository。我确定有办法,但我没有通过在这里或谷歌搜索找到任何东西。有谁知道我怎么能做到这一点?

我对 Moq 还很陌生,但可以看到花时间学习它的好处。

    /// <summary>
    /// This is a marker interface that indicates that an 
    /// Entity is an Aggregate Root.
    /// </summary>
    public interface IAggregateRoot
    {
    } 


/// <summary>
    /// Contract for Repositories. Entities that have repositories
    /// must be of type IAggregateRoot as only aggregate roots
    /// should have a repository in DDD.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IRepository<T> where T : IAggregateRoot
    {
        T FindBy(int id);
        IList<T> FindAll();
        void Add(T item);
        void Remove(T item);
        void Remove(int id);
        void Update(T item);
        void Commit();
        void RollbackAllChanges();
    }

【问题讨论】:

    标签: c# unit-testing generics moq


    【解决方案1】:

    应该不是问题:

    public interface IAggregateRoot { }
    
    class Test : IAggregateRoot { }
    
    public interface IRepository<T> where T : IAggregateRoot
    {
        // ...
        IList<T> FindAll();
        void Add(T item);
        // ...
     }
    
    class Program
    {
        static void Main(string[] args)
        {
            // create Mock
            var m = new Moq.Mock<IRepository<Test>>();
    
            // some examples
            m.Setup(r => r.Add(Moq.It.IsAny<Test>()));
            m.Setup(r => r.FindAll()).Returns(new List<Test>());
            m.VerifyAll();
        }
    }
    

    【讨论】:

      【解决方案2】:

      您必须指定类型,据我所知,没有直接的方法可以返回通用类型的项目。

      mock = new Mock<IRepository<string>>();    
      mock.Setup(x => x.FindAll()).Returns("abc");
      

      【讨论】:

        【解决方案3】:

        我在测试中创建了一个虚拟的具体类 - 或使用现有的实体类型。

        在不创建具体类的情况下,通过 100 圈也许可以做到这一点,但我认为这不值得。

        【讨论】:

        • 确保具有虚拟类的程序集在 AssemblyInfo.cs 中有 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 并且该类至少是内部的