Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Jenkins未通过单元CanExecute测试';s方法不确定性_C#_Wpf_Jenkins_Moq_Canexecute - Fatal编程技术网

C# Jenkins未通过单元CanExecute测试';s方法不确定性

C# Jenkins未通过单元CanExecute测试';s方法不确定性,c#,wpf,jenkins,moq,canexecute,C#,Wpf,Jenkins,Moq,Canexecute,在我们的项目中,我们有很多可以执行各种命令的测试。 当我们使用VisualStudio测试或AxoCover时,所有测试都正确通过 在执行“CanExecute”之前,我们尝试添加一些以前的对象初始化,有时它会起作用(或者我们认为是这样) 我有一个测试: [TestCase(true, true, TestName = "Command_InEditMode_CanExecute")] [TestCase(false, false, TestName = "Command_NotInEditMo

在我们的项目中,我们有很多可以执行各种命令的测试。 当我们使用VisualStudio测试或AxoCover时,所有测试都正确通过

在执行“CanExecute”之前,我们尝试添加一些以前的对象初始化,有时它会起作用(或者我们认为是这样)

我有一个测试:

[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));
}
问题是,这只发生在詹金斯身上,而且非常不确定

编辑:

好的,还有一件事要考虑。属性InEditMode放置在SomeModelView的基父类中

我在示例中为您合并了代码

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);
    }
}
我们认为这可能是相关的,那个对象认为在基类初始化之前就已经初始化了。但这很难用詹金斯来证实


解决方案 我已经创建了一个属性类:

[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()
{}

闻起来像是垃圾收集的问题。在您的示例中,我没有看到任何让我吃惊的东西,尽管代码示例不完整(where is
RegisterCommands
invoked?),因此可能缺少一些关键的东西

有关详细信息,请参阅源代码。它对您传入的操作具有弱引用,一旦收集到该操作,
CanExecute
将返回
false
。请参阅我的答案,以了解发生这种情况的示例


我重申@Nkosi的评论,创建一个最小的例子,而不是向我们展示零碎的东西

您的代码中有赛车条件吗?有时我们也会有类似的测试,因为我们的测试是在多线程中执行的。您在上面看到的代码在我们的项目中几乎完全相同。我们有时有非常简单的CanExecute,如上所述。据我所知,我们的Jenkins没有在多个线程中执行测试。我添加了第二个测试用例。CanExecute方法在代码中。只是:()=>InEditMode@PiotrZieliński在您的示例中,
InEditMode
不是
virtual
时,如何能够被覆盖?提供一个可用于重现问题的实例,以便更好地理解所询问的内容。testedViewModel.Object是模拟对象的实例。命令是类中属性的名称,该类包含带有匿名函数的RelayCommand对象。你是对的,InEditMode是一个虚拟类型,忘了在上面的代码中添加它。是的,这是一个垃圾收集器问题!我将在我原来的帖子中添加解决方案。@PiotrZieliński不是这个解决方案的超级粉丝。您的代码有一个bug(某些对象没有被正确保留),在某个时候,您会在非测试环境中遇到它。在测试期间禁用GC只会掩盖错误。
[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;
}
[GarbageCollectorDisabler]
[TestCase(TestName = "SomeTest_InEditMode_CanExecute")]
public void SomeTestCanExecute()
{}