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