2

我正在使用 MsTest 和 RhinoMocks 一起练习 TDD,并且我试图尽可能地懒惰,即尽可能使用 VS2012 自动生成。但是使用 Arrange-Act-Assert 方法创建一个完整的测试方法并不总是正确的,只是为了设置我的类及其构造函数和属性。

目前,我发现在我的测试类中创建一些属性是最容易的——即使我不使用它们——仅用于代码生成的目的。我的问题是,这是一个坏习惯吗,有没有更好/更简单的方法呢?欢迎任何评论,无论好坏;谢谢!

[TestClass]
public class MainViewModelTest
{
    private MainViewModel MainViewModel
    {
        get
        {
            var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();

            var viewModel = new MainViewModel(facilityDataEntity)
            {
                FacilityValue = string.Empty,
                FacilityLabel = string.Empty
            };

            return viewModel;
        }
    }

    private MainViewModel MainViewModelWithFacilityAndShopOrderData
    {
        get
        {
            var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
            var shopOrderDataEntity = MockRepository.GenerateStub<ShopOrderDataEntity>();

            var viewModel = new MainViewModel(facilityDataEntity, shopOrderDataEntity)
            {
                FacilityValue = string.Empty,
                FacilityLabel = string.Empty,
                ShopOrder = 99999999,
                RequiredQuantity = 0M,
                ItemCode = string.Empty,
                ItemDescription = string.Empty
            };

            return viewModel;
        }
    }

    [TestMethod]
    public void MainViewModel_TranslateDataEntityListMethodReturnsMainViewModelRecords()
    {
        // Arrange
        var facilityDataEntityList = MockRepository.GenerateStub<IEnumerable<FacilityDataEntity>>();
        var shopOrderDataEntityList = MockRepository.GenerateStub<IEnumerable<ShopOrderDataEntity>>();

        // Act
        IEnumerable<MainViewModel> facilityResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList);
        IEnumerable<MainViewModel> shopOrderResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList, shopOrderDataEntityList);

        // Assert
        Assert.IsInstanceOfType(facilityResults, typeof(IEnumerable<MainViewModel>));
        Assert.IsInstanceOfType(shopOrderResults, typeof(IEnumerable<MainViewModel>));
    }
}
4

2 回答 2

3

在您的测试类中包含通用代码并没有错,但我会避免在您的测试之间潜在地共享状态。

您可以在此处使用两种方法。

类/测试初始化

正如彼得在他的评论中提到的那样,包含初始化方法来为您做这类事情很容易。

//Only runs once per test run
[ClassInitialize]
public void InitClass(){

   //Ideally this should be reserved for expensive operations
   // or for setting properties that are static throughout
   // the lifetime of your test.

}

//Runs for every test
[TestInitialize]
public void TestInit(){

   //Here you can setup common stub/mock behavior
   // that will be common for every test, but ensure
   // it is clean for each test run

}

设置/工厂方法

另一种选择是创建专门的设置或工厂方法,可用于减少重复的测试代码并使测试的意图更清晰。

[TestMethod]
public void ShouldFailIfUserNameIsTed(){

   var user = SetupUserScenario("Ted");

   var result = _myUserService.Validate(user);

   Assert.IsFalse(result);
}

private User SetupUserScenario(String username){

   var user = new User();
   user.Name = username;

   //Do a bunch of other necessary setup

   return user;
}

希望这一切都有意义,但我也提醒您不要对此过于疯狂。如果你在设置方法中投入了太多东西,那么你的测试就会变得不那么清晰。您应该能够阅读测试并弄清楚发生了什么,而无需检查代码中的许多其他地方。

于 2013-03-07T15:42:59.317 回答
1

这就是ClassInitialize功能的用途。我会先选择预期和推荐的方式来做某事。它更容易识别,并且花费更少的时间来理解代码。

于 2013-03-08T14:53:11.927 回答