Дженкинс провалил недопустимые методы тестирования CanExecute

У нас есть много тестов 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)

Проблема в том, что это происходит только с Дженкинсом, и это очень недетерминировано.

EDIT:

Хорошо, еще одна вещь для размышления. Свойство 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()
{}

Ответ 1

Пахнет для меня проблемой сбора мусора. Я не вижу ничего, что выскочило на меня в вашем примере, хотя пример кода неполон (где вызывается RegisterCommands?), Поэтому может быть упущено что-то важное.

См. Источник для RelayCommand.CanExecute(). Он содержит слабую ссылку на действие, которое вы передаете, и как только это действие будет собрано, CanExecute вернет false. Смотрите мой ответ здесь для примера этого.

Я повторяю комментарий @Nkosi, создаю минимальный пример, а не показываю нам кусочки.