【问题标题】:Resolution for Model View Presenter Testing... Do I use DTO's or Domain objects or both?模型视图演示者测试的分辨率...我使用 DTO 或域对象还是两者都使用?
【发布时间】:2011-12-07 04:27:56
【问题描述】:

基本问题是如何测试演示者。

采取: 域对象(最终会被持久化到数据库中) 基本属性是 Id(DB ID,Int/GUID/Whatever)和 TransientID(保存前的本地 ID,GUID)

域对象

namespace domain { public class DomainObject { private int _id; private Guid transientId; public DomainObject() { _transient_Id = Guid.NewGuid(); } } }

PresenterTest:

var repository = Mock.StrictMock(); var view = Mock.StrictMock(); view.Save += null; var saveEvent = LastCall.Ignore().GetEventRaiser(); var domainObject = new DomainObject() {Id = 0, Attribute = "Blah"}; Mock.ExpectCall(Repository.Save(domainObject)).Returns(True); Mock.ReplayAll(); var sut = new Presenter(repository, view); Save_Event.raise(view, EventArgs.Empty); Mock.Verify()

所以这里的问题是域对象身份是用 ID 计算的,而它是用瞬态 ID 计算的,没有办法知道瞬态 ID 是什么,所以我不能让模拟存储库检查是否相等。

目前的解决方法是:

1) LastCall.Ignore 并满足于 jsut 测试方法被调用但不测试调用的内容。

2) 编写 DTO 进行测试并保存到服务中。服务然后处理到域的映射。

3) 编写一个虚假的 testRepository,使用自定义逻辑来确定成功。

--1 不测试大部分逻辑。 --2 是很多额外的代码,没有什么好用的 --3 似乎很脆弱。

现在我倾向于 DTO 和理论上的服务,它在层之间提供最大的隔离,但可能 75% 是不必要的......

【问题讨论】:

    标签: c# design-patterns tdd mocking mvp


    【解决方案1】:

    没有办法知道瞬态 ID 是什么,所以我不能让模拟存储库检查是否相等。

    其实我觉得这里有机会。

    您可以创建自己的 GuidFactory 类来生成 GUID,而不是调用 Guid.NewGuid()。默认情况下,它会在内部使用Guid.NewGuid(),但您可以控制它进行测试。

    public static class GuidFactory
    {
        static Func<Guid> _strategy = () => Guid.NewGuid();
    
        public static Guid Build()
        {
            return _strategy();
        }
    
        public static void SetStrategy(Func<Guid> strategy)
        {
            _strategy = strategy;
        }
    }
    

    在您的构造函数中,将Guid.NewGuid() 替换为GuidFactory.Build()

    在您的测试设置中,您可以覆盖策略以满足您的需求 - 返回一个已知的 Guid,您可以在测试的其他地方使用它,或者只是将默认结果输出到一个字段。

    例如:

    public class PseudoTest
    {
        IList<Guid> GeneratedGuids = new List<Guid>();
    
        public void SetUpTest()
        {
            GuidFactory.SetStrategy(() => 
            {
                var result = Guid.NewGuid();
                GeneratedGuids.Add(result);
                return result;
            });
        }
    
        public void Test()
        {
            systemUnderTest.DoSomething();
            Assert.AreEqual(GeneratedGuids.Last(), someOtherGuid);
        }
    }
    

    【讨论】:

      【解决方案2】:

      WPF 帮助我意识到,如果在 Controller/Presenter/VM 上进行任何测试,您真的不需要做太多测试。您确实应该将所有测试集中在您使用的模型和服务上。所有业务逻辑都应该在那里,视图模型或演示者或控制器应该尽可能轻,唯一的作用是在模型和视图之间来回传输。

      当按钮命令发送给演示者时,测试您是否调用服务有什么意义?或者测试一个事件是否正确连接?

      不要误会我的意思,我仍然有一个非常小的用于视图模型或控制器的测试夹具,但实际上测试的重点应该放在模型上,让集成测试测试视图和演示者的成功。

      瘦控制器/虚拟机/演示者。 胖模特。

      这是我的答案,因为我在尝试测试视图模型时遇到了同样的问题,我浪费了很多时间试图弄清楚如何最好地测试它们,而另一位开发人员用这个论点就模型视图模式进行了精彩的演讲。不要花太多时间为这些做测试,专注于模型/服务。

      【讨论】:

      • 同意,但是这个项目是关于全面测试表示层... IE 熟悉 MVP 模式并构建一个完全可测试的表示层。真的,这个答案与 LastCall.Ignore 相同,IE 我确认事件是有线的,但不关心演示者中的逻辑是否正确运行。所以,你是对的......在任何现实世界的情况下:)
      猜你喜欢
      • 1970-01-01
      • 2010-10-05
      • 2019-10-24
      • 2016-03-14
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      相关资源
      最近更新 更多