我正在使用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>));
}
}
答案 0 :(得分:3)
在测试类中包含公共代码并没有错,但我会避免在测试之间共享状态。
您可以在这里使用两种方法。
正如Peter在他的评论中提到的那样,很容易包含初始化方法来为你做这类事情。
//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;
}
希望这一切都有道理,但我也提醒你不要对此过于疯狂。如果你在设置方法中加入太多东西,那么你的测试就不那么清楚了。您应该能够阅读测试并找出正在发生的事情,而无需检查代码中的其他一些地方。
答案 1 :(得分:1)
这就是ClassInitialize
功能的用途。我会先选择预期和推荐的做事方式。它更容易识别,并且花费更少的时间来理解代码。