【问题标题】:Creating Mock reference and setup methods for complex operations using MOQ使用 MOQ 为复杂操作创建模拟参考和设置方法
【发布时间】:2017-07-03 06:54:01
【问题描述】:

我有两个方法,OpenCertificateStore 和 FindCertificateBySubjectName 并实现如下:

 public void OpenCertificateStore()
        {
            if (_certificateStore == default(X509Store))
                _certificateStore = new X509Store(StoreLocation.CurrentUser);

            _certificateStore.Open(OpenFlags.ReadOnly | OpenFlags.IncludeArchived);
        }

        public X509Certificate2Collection FindCertificateBySubjectName(string certificateSubjectName)
        {
            X509Certificate2Collection certificates = new X509Certificate2Collection();
            if (_certificateStore != default(X509Store))
            {
                certificates = _certificateStore.Certificates.Find(X509FindType.FindBySubjectName, certificateSubjectName, true);
            }

            return certificates;
        }

我的单元测试如下:

[TestClass]
    public class MyHealthTests
    {
        private Mock<Logger> _logger;
        private Mock<MYCertificateManager> _certManager;

        [TestInitialize]
        public void Initialize()
        {
             _logger = new Mock<Logger>();
             _certManager = new Mock<MYCertificateManager>();
        }

        [TestMethod]
        public void PassName_FindCertiFicatebyName_ShouldReturnValid()
        {


            MyCertificateHelper myCertHelper = new MyCertificateHelper(_logger.Object,_certManager.Object);

            myCertHelper.OpenCertificateStore();
            var certNameCollection = myCertHelper.FindCertificateBySubjectName("Valid Cert Name");
            Assert.IsNotNull(certNameCollection);
            Assert.IsTrue(certNameCollection.Count > 0);
        }
    }

这很好用,但如果我能找到一种模拟myCertHelper的方法会更好。

如果我确实删除了它们,它会返回 null,因为它没有查询实际的证书存储。

【问题讨论】:

    标签: c# .net unit-testing mocking moq


    【解决方案1】:

    你如何模拟MyCertificateHelper

    你没有。

    这样做没有任何好处。如果你这样做了,那么你测试中的所有类都将被模拟出来,你将不再实际测试任何代码。此时,您不妨删除测试。它不会做任何事情,但要花钱维护它。


    • My 前缀是没有用的。比无用更糟糕的是,它嘈杂且令人分心。算了吧。
    • 我不喜欢您设计中的时间耦合。我不喜欢调用像OpenInit 这样的方法。很容易忘记调用它或调用它太多次。如果构造函数将类置于可用状态会更好。
    • 很高兴您正在注入和踢记录器,但我发现注入记录器是一种代码味道。我发现让我的课程引发事件并让记录器监听这些事件要好得多。它消除了一直模拟记录器的需要,并为其他代码提供了很好的钩子来利用。这种事件驱动设计的代码对扩展更加开放,但对修改关闭。

    【讨论】:

    • 'My ' 被替换为实际类名,因为我不想公开类名。它有一个客户端名称的前缀:)
    • 这也好不到哪里去@Simsons。这就是命名空间的用途。
    • 我对二和三持怀疑态度。您首先配置了一些对象,然后使用 Open 或其他方法使它们可用(请参阅 SqlConnection)。这种模式有一个名字,但我忘记了……为日志记录引发事件限制了使用许多高级场景的可能性。使用 Autofac 之类的帮助程序,即使注入多个服务也不是问题,而且您不必在每个类中实现引发事件。
    • 这取决于用例@t3chb0t,但我已经处理了足够多的非常嘈杂的日志,我真的更喜欢以尽可能高的级别记录。至于“开放”的东西,Ado 教会了我讨厌这种模式,你会发现 McConnel 在 Code Complete 中反对它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 2010-11-12
    • 2016-09-21
    • 1970-01-01
    相关资源
    最近更新 更多