Jenkins 失败单元 CanExecute 测试的方法不确定
Jenkins failed unit CanExecute test's methods nondeterministic
我们对项目中的各种命令进行了很多 CanExecute 测试。
当我们使用 Visual Studio 测试或 AxoCover.
时,所有测试都正确通过
我们尝试在执行 'CanExecute' 之前添加一些先前的对象初始化,有时它有效(或者我们认为有效)。
testedViewModel.Object.InEditMode = inEditMode;
我有一个测试:
[TestCase(true, true, TestName = "Command_InEditMode_CanExecute")]
[TestCase(false, false, TestName = "Command_NotInEditMode_CannotExecute")]
public void CommandCanExecute(bool inEditMode, bool expectedResult)
{
var testedViewModel =
new Mock<SomeViewModel>(inEditMode)
{
CallBase = true
};
testedViewModel.Setup(x => x.InEditMode).Returns(inEditMode);
Assert.AreEqual(expectedResult, testedViewModel.Object.Command.CanExecute(null));
}
有时(不总是)当 Jenkins 进行构建和 运行 单元测试时,一些可以执行的测试失败并显示消息:
MESSAGE:
Expected: True
But was: False
+++++++++++++++++++
STACK TRACE:
at Project.CommandCanExecute(Boolean inEditMode, Boolean expectedResult)
问题是这只发生在 Jenkins 上,而且非常不确定。
编辑:
好的,还有一件事要考虑。 属性 InEditMode 位于 SomeModelView 的基础父级 class 中。
我在示例中为您合并了代码。
public BaseViewModel
{
public virtual bool InEditMode {get; set;}
}
public SomeViewModel : BaseViewModel
{
public SomeViewModel () : base ()
{
}
public ICommand Command { get; set; }
public virtual void RegisterCommands()
{
Command = new RelayCommand(/*Do something*/, () => InEditMode);
}
}
我们认为这可能是相关的,该对象认为在基 class 初始化完成之前就已初始化。但这很难用 Jenkins 来检查。
解决方案
我创建了一个属性 class:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Assembly, AllowMultiple = true)]
public class GarbageCollectorDisabler : Attribute, ITestAction
{
public void BeforeTest(ITest test)
{
GC.TryStartNoGCRegion(2048 * 4096);
}
public void AfterTest(ITest test)
{
GC.EndNoGCRegion();
}
public ActionTargets Targets => ActionTargets.Test;
}
然后我可以为每个 'CanExecute' 测试这个属性:
[GarbageCollectorDisabler]
[TestCase(TestName = "SomeTest_InEditMode_CanExecute")]
public void SomeTestCanExecute()
{}
我觉得像是垃圾收集问题。尽管代码示例不完整(在哪里调用了 RegisterCommands
?),但我在您的示例中没有看到任何让我印象深刻的东西,所以可能缺少一些重要的东西。
请参阅 RelayCommand.CanExecute()
. It takes a weak reference to the action you pass in, and once that action is collected CanExecute
will return false
. See my answer here 的来源以了解发生这种情况的示例。
我重申@Nkosi 的评论,创建一个最小的示例而不是向我们展示点点滴滴。
我们对项目中的各种命令进行了很多 CanExecute 测试。 当我们使用 Visual Studio 测试或 AxoCover.
时,所有测试都正确通过我们尝试在执行 'CanExecute' 之前添加一些先前的对象初始化,有时它有效(或者我们认为有效)。
testedViewModel.Object.InEditMode = inEditMode;
我有一个测试:
[TestCase(true, true, TestName = "Command_InEditMode_CanExecute")]
[TestCase(false, false, TestName = "Command_NotInEditMode_CannotExecute")]
public void CommandCanExecute(bool inEditMode, bool expectedResult)
{
var testedViewModel =
new Mock<SomeViewModel>(inEditMode)
{
CallBase = true
};
testedViewModel.Setup(x => x.InEditMode).Returns(inEditMode);
Assert.AreEqual(expectedResult, testedViewModel.Object.Command.CanExecute(null));
}
有时(不总是)当 Jenkins 进行构建和 运行 单元测试时,一些可以执行的测试失败并显示消息:
MESSAGE:
Expected: True
But was: False
+++++++++++++++++++
STACK TRACE:
at Project.CommandCanExecute(Boolean inEditMode, Boolean expectedResult)
问题是这只发生在 Jenkins 上,而且非常不确定。
编辑:
好的,还有一件事要考虑。 属性 InEditMode 位于 SomeModelView 的基础父级 class 中。
我在示例中为您合并了代码。
public BaseViewModel
{
public virtual bool InEditMode {get; set;}
}
public SomeViewModel : BaseViewModel
{
public SomeViewModel () : base ()
{
}
public ICommand Command { get; set; }
public virtual void RegisterCommands()
{
Command = new RelayCommand(/*Do something*/, () => InEditMode);
}
}
我们认为这可能是相关的,该对象认为在基 class 初始化完成之前就已初始化。但这很难用 Jenkins 来检查。
解决方案
我创建了一个属性 class:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Assembly, AllowMultiple = true)]
public class GarbageCollectorDisabler : Attribute, ITestAction
{
public void BeforeTest(ITest test)
{
GC.TryStartNoGCRegion(2048 * 4096);
}
public void AfterTest(ITest test)
{
GC.EndNoGCRegion();
}
public ActionTargets Targets => ActionTargets.Test;
}
然后我可以为每个 'CanExecute' 测试这个属性:
[GarbageCollectorDisabler]
[TestCase(TestName = "SomeTest_InEditMode_CanExecute")]
public void SomeTestCanExecute()
{}
我觉得像是垃圾收集问题。尽管代码示例不完整(在哪里调用了 RegisterCommands
?),但我在您的示例中没有看到任何让我印象深刻的东西,所以可能缺少一些重要的东西。
请参阅 RelayCommand.CanExecute()
. It takes a weak reference to the action you pass in, and once that action is collected CanExecute
will return false
. See my answer here 的来源以了解发生这种情况的示例。
我重申@Nkosi 的评论,创建一个最小的示例而不是向我们展示点点滴滴。