【问题标题】:Mocking Guid.NewGuid()模拟 Guid.NewGuid()
【发布时间】:2012-07-20 07:39:00
【问题描述】:

假设我有以下实体:

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public Guid UserGuid { get; set; }
    public Guid ConfirmationGuid { get; set; }
}

还有如下接口方法:

void CreateUser(string username);

部分实现应该创建两个新的 GUID:一个用于UserGuid,另一个用于ConfirmationGuid。他们应该通过将值设置为 Guid.NewGuid() 来做到这一点。

我已经使用接口抽象了 Guid.NewGuid():

public interface IGuidService
{
    Guid NewGuid();
}

所以当只需要一个新的 GUID 时,我可以轻松地模拟它。但我不确定如何从一个方法中模拟对同一方法的两个不同调用,以便它们返回不同的值。

【问题讨论】:

    标签: c# unit-testing mocking tdd moq


    【解决方案1】:

    如果您使用的是起订量,则可以使用:

    mockGuidService.SetupSequence(gs => gs.NewGuid())
        .Returns( ...some value here...)
        .Returns( ...another value here... );
    

    我想您还可以执行以下操作:

    mockGuidService.Setup(gs => gs.NewGuid())
        .Returns(() => ...compute a value here...);
    

    不过,除非您只是在返回函数中提供一个随机值,否则顺序知识似乎仍然很重要。

    【讨论】:

    • 但这不是假设我在实现中以特定顺序设置属性吗?这不是掩盖了我对考试的担忧吗?换句话说,这些字段可以按任何顺序设置,如果由于某种原因我在不更新测试的情况下更改了此顺序,理想情况下我的测试应该仍然通过。
    • 嗯......你正在进入状态与行为测试。如果不假设有关呼叫顺序的知识,我不确定如何回答这个问题。
    • 如果我理解正确,如果您更改分配顺序,您不希望Assert.AreEqual(guid1, user.UserGuid); Assert.AreEqual(guid2, user.ConfirmationGuid); 失败。相反,您应该使用某种与顺序无关的集合断言(在 nunit 和 mstest 中都可用):CollectionAssert.AreEquivalent(new[] { guid1, guid2 }, new[] { user.UserGuid, user.ConfirmationGuid });
    • @MattH,我很有可能会模糊状态测试和行为测试之间的界限。您是否建议重新考虑我的测试设计?
    • @mikez,是的,结合马特的答案应该可以解决问题。谢谢大家。
    【解决方案2】:

    如果您不能像 @Matt 的示例那样使用 Moq,那么您可以构建自己的类,它基本上可以做同样的事情。

    public class GuidSequenceMocker
    {
        private readonly IList<Guid> _guidSequence = new[]
                                                         {
                                                             new Guid("{CF0A8C1C-F2D0-41A1-A12C-53D9BE513A1C}"),
                                                             new Guid("{75CC87A6-EF71-491C-BECE-CA3C5FE1DB94}"),
                                                             new Guid("{E471131F-60C0-46F6-A980-11A37BE97473}"),
                                                             new Guid("{48D9AEA3-FDF6-46EE-A0D7-DFCC64D7FCEC}"),
                                                             new Guid("{219BEE77-DD22-4116-B862-9A905C400FEB}") 
                                                         };
        private int _counter = -1;
    
        public Guid Next()
        {
            _counter++;
    
            // add in logic here to avoid IndexOutOfRangeException
            return _guidSequence[_counter];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-09
      • 2010-11-22
      • 1970-01-01
      • 2023-02-10
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 2015-01-08
      • 1970-01-01
      相关资源
      最近更新 更多