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;
        }
    }
}

テストの目的で、これらのイベントを静的リストにキャプチャしたいと思います。これを行うための最良の方法は何ですか?

アップデート

この問題は、テストが実行される順序が原因で発生しました(Alexanderが以下で指摘しているように、これは保証されていません)。私の仕様の1つで、模擬イベントの発行元を登録しました。仕様が異なる順序で実行されることが多いという事実は、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 に答える