我正在使用nunit和ninject在VS2012的新MVC 4解决方案中运行ncrunch。
当我第一次打开解决方案时,所有50个左右的测试运行并成功通过。
在我进行任何代码更改后(即使只是添加了空白空间)ncrunch报告我的大部分单元测试都失败了。如果我在ncrunch窗口中按“运行所有测试”,就会发生同样的事情。
但如果你点击'运行所有可见的测试'按钮,所有50个测试再次通过并且ncrunch报告一切正常。
此外,当您单独运行每个测试时,它们每次都会通过。
当他们失败时,他们似乎在我的ninject设置代码中失败了
错误:ControllerTestSetup中的TestFixtureSetUp失败
public class ControllerTestSetup
{
[SetUp]
public void InitIntegrationTest()
{
var context = IntegrationTestContext.Instance;
context.Init();
context.NinjectKernel.Load<MediGapWebTestModule>();
}
[TearDown]
public void DisposeIntegrationTest()
{
IntegrationTestContext.Instance.Dispose();
}
}
public class IntegrationTestContext : IDisposable
{
private static IntegrationTestContext _instance = null;
private static readonly object _monitor = new object();
private IntegrationTestContext() { }
public static IntegrationTestContext Instance
{
get
{
if (_instance == null)
{
lock (_monitor)
{
if (_instance == null)
{
_instance = new IntegrationTestContext();
}
}
}
return _instance;
}
}
}
所有测试也都在resharper测试运行器中运行,每次都没有问题。
有谁知道造成这种情况的原因是什么?
我猜它与Instance属性中的单例锁定代码有关,但我不确定。
=============================================== =============================== 进展:
我能够通过将它包装在try catch语句中并将错误写入输出窗口来跟踪上述ninject设置方法中的错误。
异常是由于尝试不止一次加载模块引起的,即使我绝对没有,我也不使用任何类型的自动模块加载。
这发生在
行LocalSessionFactoryModule.SetMappingAssemblies(() => new[] { typeof(ProviderMap).Assembly });
_kernel.Load<LocalSessionFactoryModule>();
_sessionFactory = _kernel.Get<ISessionFactory>();
其中LocalSessionFactoryModule是为NinjectModule类派生的ninject模块类。
为什么这只会在ncrunch中发生,我该怎么做才能解决这个问题?有没有办法检查模块是否已经加载?
答案 0 :(得分:5)
NCrunch永远不会在同一个进程中执行测试并发,所以除非你的测试逻辑中有多线程行为,否则应该可以肯定地说这不是由单例锁定或线程引起的问题
由于您已经尝试禁用并行执行,这没有什么区别,我假设问题不会是由于在测试运行程序进程之外并发使用资源(即磁盘上的文件)引起的。
这意味着问题几乎肯定与执行测试的顺序有关。几乎所有的手动测试运行器(包括Resharper)都将从头到尾按照定义的顺序运行测试。这有利于一致性,但它可以掩盖当测试以不一致/随机顺序运行时可能出现的问题。 NCrunch将按优先级顺序执行测试,并且还可以在测试运行之间重用测试过程,如果没有考虑到这一点,可能会使测试的运行时行为不同。
表面(并因此调试)与序列相关的问题的一种有用方法是尝试使用NCrunch以手动定义的顺序运行测试。如果右键单击NCrunch测试窗口中的测试,则在“高级”菜单下,您将找到使用现有任务运行程序进程运行测试的选项。对几个测试尝试此操作,看看是否可以重现显示问题的序列。当它发生时,您应该能够轻松地将调试器放到测试中并找出它失败的原因。
大多数与序列相关的问题都是由未清除的静态成员引起的,因此请确保每个测试都是在假设现有状态可能被另一个已在流程中运行的测试遗留下来的情况下编写的。另一个选择是确保通过拆除测试完全清除所有状态(尽管在我看来,这通常是一种不那么实用的方法)。