3

我正在尝试在测试之前运行一些初始化代码。我已经尝试过其他问题中的建议,但它似乎不起作用。我的域模型通过以下类引发事件:

public static class DomainEvents
{
    private static readonly object @lock = new object();
    private static Action<IDomainEvent> raiseEvent;

    public static void Raise<TEvent>(TEvent @event) where TEvent : class, IDomainEvent 
    {
         // omitted for brevity
    }

    public static void RegisterEventPublisher(Action<IDomainEvent> eventPublisher)
    {
        lock (@lock)
        {
            raiseEvent = eventPublisher;
        }
    }
}

出于测试目的,我想在静态列表中捕获这些事件。这样做的最佳方法是什么?

更新

问题是由运行测试的顺序引起的(正如亚历山大在下面指出的,不能保证)。在我的一个规范中,我注册了一个模拟事件发布者。规范经常以不同的顺序运行的事实意味着 a) 一开始我不知道我有问题(“问题”规范总是最后运行)和 b) 一旦我开始遇到问题,失败的测试通常会在运行之间有所不同(使其更加混乱)。

吸取的教训 - 在每个上下文运行后清理所有静态资源。您可以通过实施ICleanupAfterEveryContextInAssembly.

4

2 回答 2

4

也许我误解了这个问题,但基本模式是:

public class WhenSomeDomainEventIsRaised
{
    private IList<IDomainEvent> EventsRaised = new List<IDomainEvent>();

    Establish context = () => 
    {
        // subscribe to events; when raised, add to EventsRaised list
    }
}

如果您想对所有测试或测试子集执行此操作:

public abstract class DomainSpecification
{
    protected IList<IDomainEvent> EventsRaised = new List<IDomainEvent>();

    Establish context = () => 
    {
        // subscribe to events; when raised, add to EventsRaised list
    }
}

您可以让所有需要此行为的规范都从此类继承,而 MSpec 将负责Establish沿继承层次结构运行所有块。

于 2012-04-18T21:24:13.383 回答
2

对我有用:

using System;
using System.Collections.Generic;

using Machine.Specifications;

namespace AssemblyContextSpecs
{
  public static class DomainEvents
  {
    static readonly object @lock = new object();

    static Action<IDomainEvent> raiseEvent;

    public static void Raise<TEvent>(TEvent @event) where TEvent : class, IDomainEvent
    {
      raiseEvent(@event);
    }

    public static void RegisterEventPublisher(Action<IDomainEvent> eventPublisher)
    {
      lock (@lock)
      {
        raiseEvent = eventPublisher;
      }
    }
  }

  public interface IDomainEvent
  {
  }

  class FooEvent : IDomainEvent
  {
  }

  public class DomainEventsContext : IAssemblyContext
  {
    internal static IList<IDomainEvent> Events = new List<IDomainEvent>();

    public void OnAssemblyStart()
    {
      DomainEvents.RegisterEventPublisher(x => Events.Add(x));
    }

    public void OnAssemblyComplete()
    {
    }
  }

  public class When_a_domain_event_is_raised
  {
    Because of = () => DomainEvents.Raise(new FooEvent());

    It should_capture_the_event =
      () => DomainEventsContext.Events.ShouldContain(x => x.GetType() == typeof(FooEvent));
  }
}

RegisterEventPublisher应该RegisterEventSubscriber吗?

于 2012-04-19T07:54:33.037 回答