瞧瞧。我想介绍我的(部分)解决方案(强制夹具和设置隔离)。这并同时解决了管道代码的问题。
我基本上将一个自动模拟容器放在夹具的一个实例中,并确保为每个规范重新创建夹具。如果需要一些其他设置,只需继承或添加到夹具。
(注意这使用结构图和结构图/起订量/自动模拟容器。我确信对于不同的容器/模拟框架都是一样的。)
/// <summary>
/// This is a base class for all the specs. Note this spec is NOT thread safe. (But then
/// I don't see MSpec running parallel tests anyway)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <remarks>
/// This class provides setup of a fixture which contains a) access to class under test
/// b) an auto mocking container and c) enforce a clean fixture for every spec.
/// </remarks>
public abstract class BaseSpec<T>
where T : class
{
public static TestFixture Fixture;
private Establish a_new_context = () =>
{
Fixture = new TestFixture();
MockedTypes = new Dictionary<Type, Action>();
};
/// <summary>
/// This dictionary holds a list of mocks that need to be verified by the behavior.
/// </summary>
private static Dictionary<Type, Action> MockedTypes;
/// <summary>
/// Gets the mock of a requested type, and it creates a verify method that is used
/// in the "AllMocksVerified" behavior.
/// </summary>
/// <typeparam name="TMock"></typeparam>
/// <returns></returns>
public static Mock<TMock> GetMock<TMock>()
where TMock : class
{
var mock = Mock.Get(Fixture.Context.Get<TMock>());
if (!MockedTypes.ContainsKey(typeof(TMock)))
MockedTypes.Add(typeof(TMock), mock.VerifyAll);
return mock;
}
[Behaviors]
public class AllMocksVerified
{
private Machine.Specifications.It should_verify_all =
() =>
{
foreach (var mockedType in MockedTypes)
{
mockedType.Value();
}
};
}
public class TestFixture
{
public MoqAutoMocker<T> Context { get; private set; }
public T TestTarget
{
get { return Context.ClassUnderTest; }
}
public TestFixture()
{
Context = new MoqAutoMocker<T>();
}
}
}
这是一个示例用法。
public class get_existing_goo : BaseSpec<ClassToTest>
{
private static readonly Goo Param = new Goo();
private Establish goo_exist =
() => GetMock<Foo>()
.Setup(a => a.MockMethod())
.Returns(Param);
private static Goo result;
private Because goo_is_retrieved =
() => result = Fixture.Context.ClassUnderTest.MethodToTest();
private It should_not_be_null =
() => result.ShouldEqual(Param);
}
基本上,如果需要共享某些东西,请将其放在夹具本身的实例中。这种“强制”分离……有些什么。
在这方面我还是更喜欢 Xunit。