【问题标题】:Moq: How to retrieve ID of mocked objectMoq:如何检索模拟对象的 ID
【发布时间】:2016-04-20 08:07:45
【问题描述】:

我已经成功创建了一个模拟的Person 对象,现在我正在尝试使用我的AddChild() 方法通过它的'Id 将一个子对象添加到对象中。我的测试如下所示:

public class PersonManagerMockTest
{
    private static Guid personGuid;

    [ClassInitialize]
    public static void Init(TestContext test)
    {
        personGuid = Guid.NewGuid();
    }

    [TestMethod]
    public void AddNewPerson()
    {
        //Arrange
        var mockDbSet = new Mock<DbSet<Person>>();
        mockDbSet.Setup(x => x.Add(It.IsAny<Person>()))
            .Returns<Person>(p => p);

        var mockContext = new Mock<IHiveTiesContext>();
        mockContext.Setup(x => x.People)
            .Returns(mockDbSet.Object);
        var manager = new Manager(mockContext.Object);

        //Assert
        var _person = manager.CreatePerson("Winston", "Gabriel", DateTime.Now, 'M', personGuid);

        var fatherid = mockDbSet.Object.SingleOrDefault(x => x.RowId == personGuid).Id;
        manager.AddChild(new Person
        {
            FirstName = "Aaron",
            LastName = "Gabriel",
            DOB = new DateTime(1991, 01, 16),
            FavoriteColor = "Red",
            FatherId = fatherid,
        });

        //Act
        mockDbSet.Verify(x => x.Add(It.IsAny<Person>()), Times.Once);
        mockContext.Verify(x => x.SaveChanges(), Times.Once);
    }
}

mockedPerson对象创建成功,但是问题出在这个语句:

var fatherid = mockDbSet.Object.SingleOrDefault(x => x.RowId == personGuid).Id;

我不确定如何从模拟的Person 对象中检索Id,并且我认为此语句为fatherid 返回了0,这意味着它是null。这是我第一次运行模拟,所以我还在学习。关于如何从这个模拟的Person 对象中检索Id 的任何建议? 我会感谢所有建议。谢谢。

【问题讨论】:

    标签: c# unit-testing mocking entity-framework-6 moq


    【解决方案1】:

    让 OldFoxes 对先天的回答更清楚!

     mockSet.Setup(x => x.Add(It.IsAny<ValuationCompany>()))
                    .Callback<ValuationCompany>(data.Add)
                    .Returns<ValuationCompany>(p =>
                    {
                        p.Id = 23;  // Assign whatever you want here.
                        return p;
                    });
    

    【讨论】:

    • 并且您可能必须在 DBContext 中将 ValuationCompany 属性标记为虚拟。
    【解决方案2】:

    MockObjects 没有逻辑,无法生成 Id。

    由于 DbSet 被模拟,你必须告诉它应该做什么。所以尝试像这样更改 DbSet 的设置:

    var newId = 42;
    var mockDbSet = new Mock<DbSet<Person>>();
    mockDbSet.Setup(x => x.Add(It.IsAny<Person>()))
             .Returns(newId);
    

    通过这种方式,您告诉 Moq,当有人调用 DbSet.Add 时,无论它是谁,它都必须返回 42。

    【讨论】:

    • 好的,谢谢您的反馈,我将不得不研究如何按照您的建议去做@ema
    • 是DbSet的Add方法返回新Person的Id吗?在那种情况下很容易。
    • 对不起,我没听懂你说的,能重复一遍吗? @ema
    • 如果我理解的话,类 DbSet 的方法 Add 返回新创建的 Person 的 Id。对吗?
    • 应该是,我不明白为什么它没有这样做,尽管@ema
    【解决方案3】:

    我使用了this answer中的CreateMockSet方法。

    变化:

    var mockDbSet = new Mock<DbSet<Person>>();
    mockDbSet.Setup(x => x.Add(It.IsAny<Person>()))
             .Returns<Person>(p => p);
    

    收件人:

    var persons = new List<Person>();
    
    var mockDbSet = CreateMockSet(persons.AsQueryable());
    mockDbSet.Setup(x => x.Add(It.IsAny<Person>()))
             .Callback<Person>(persons.Add)
             .Returns <Person>(p => p);
    

    Callback 方法用新的Person 实例填充persons 列表。

    CreateMockSet() 使用 persons 的返回设置创建 Mock&lt;DbSet&lt;Person&gt;&gt;(在 mockDbSet.Object 上)

    【讨论】:

    • 这如何让我访问模拟的Person 对象上的Id 属性? @OldFox
    • mockDbSet.Object.SingleOrDefault(x =&gt; x.RowId == personGuid) 将返回Person 实例,其中x.RowId == personGuid。
    • 我猜我必须在我的测试类中为CreateMockSet 创建一个新方法?还有这个方法的意义是什么,这个方法在它的主体中应该包含什么? @OldFox
    • 好吧,不,您不需要...我建议您阅读链接中的答案。它是一个通用类,具有多种扩展方法,可帮助处理 UT 中的实体框架(IMO 任何人使用实体框架并且拥有 UT 的人都必须在其 UT 的基础架构中拥有此类)。您只需将此方法设为公开即可。
    • 我做到了,我唯一的问题是我仍然无法访问这个CreateMockSet 方法。你是想让我把我的测试类改成泛型类吗?和海事组织?这个缩写是什么意思? @OldFox
    猜你喜欢
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    相关资源
    最近更新 更多