1

我使用内置的 Visual Studio 单元测试工具对 CRM 2011 执行单元测试。很多测试都在断言创建实体。

Assert.IsNull(service.GetFirstOrDefault<Contact>(contact.Id));

(GetFirstOrDefault 是一个扩展方法,它尝试通过 id 从 CRM 中检索联系人,如果没有找到则返回 null)

我想创建自己的 Assert 方法,该方法的运行方式如下:

CrmAssert.Exists(service, contact);

起初我认为继承 from 是个好主意Assert,但可惜它是一个静态类。然后我创建了一个新的静态类,如下所示:

public static class AssertCrm
{
    public static void Exists<T>(IOrganizationService service, T entity) where T : Entity
    {
        Exists(service, entity, null, null);
    }
    public static void Exists<T>(IOrganizationService service, T entity, string message) where T : Entity
    {
        Exists(service, entity, message, null);
    }

    public static void Exists<T>(IOrganizationService service, T entity, string message, params object[] parameters) where T: Entity
    {
        if (service.GetFirstOrDefault<T>(entity.Id) == null)
        {
            throw new AssertFailedException(message == null ? String.Format(message, parameters));
        }
    }
}

像这样调用:

AssertCrm.Exists(service, contact);

这很好,除了我真的应该能够设置服务一次,而不必每次都调用它:

AssertCrm.Service = service;
AssertCrm.Exists(contact);
AssertCrm.Exists(campaign);
AssertCrm.Exists(etc...);

但我相信 Visual Studio 会尝试多线程运行测试,这意味着当我设置Service静态属性时,它可能会被不同测试中的不同服务覆盖(并且IOrganizationService不是线程安全的)。

我是否需要使我的 AssertCrm 类为非静态类,这样我就不必担心多线程?有没有我错过的更简单的技术?

4

3 回答 3

0

您可以将 AssertCrm 设为单例,然后您可以将其实例化一次,所有其他调用都将使用相同的实例。

于 2013-03-29T19:12:43.537 回答
0

我个人更喜欢使用内置断言库的第一个选项。我看不出尝试将其包装在扩展方法或“帮助程序”中会带来什么好处。

如果你真的想走这条路,你可以创建一组扩展方法IOrganizationService来消除继续传递它的需要。让它更干净一些,但我仍然支持第一个。

crmService.AssertExists(contact);

顺便说一句,您为什么要在“单元”测试中使用真正的 CRM 实例?IOrganizationService在您的测试中针对模拟进行验证会更快、更易于维护。

于 2013-03-29T19:19:54.203 回答
0

经过一些额外的研究,我没有找到任何理由认为它应该(必须)是一个静态类,并且已经将它创建为一个非静态类。

给其他想做类似事情的人的一个注意事项:为所有实例方法创建静态方法重载,因为ClassName.AssertMethod()在大多数情况下确实更有意义new ClassName().AssertMethod()

于 2013-04-01T16:36:27.543 回答