我正在为MVP模式中的演示类编写单元测试。但是我在编写模拟设置代码时遇到了麻烦。
我有一个演示者,当演示者的Load方法调用我要测试视图时应该加载类属性,表字段,数据类型,设置演示者....所以当我有一个不同的事情要做演示者加载总是我有增加新的期望来测试。每次测试都越来越大。
[Test]
public void When_Presenter_Loads_View_Should_Display_Selected_Class_Properties()
{
IList<string> dataTypes =new List<string>();
IClassGenerationView view = mockRepository.StrictMock<IClassGenerationView>();
tableRepository = mockRepository.Stub<ITableRepository>();
using(mockRepository.Record())
{
SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes);
view.Presenter = null;
LastCall.IgnoreArguments();
view.DataTypes = dataTypes;
view.Show();
view.ClassProperties = classProperties;
view.TableName = "Table";
view.Table = table;
LastCall.IgnoreArguments();
}
using(mockRepository.Playback())
{
ClassGenerationPresenter presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
presenter.Load();
}
}
此代码中是否有代码味道?我该如何改进或简化?
答案 0 :(得分:2)
如果您仍想为UI逻辑编写测试,我绝对不会使用安装方法从测试中删除一些内容。在不需要上下浏览的情况下,您必须能够理解测试的原因和结果。相反,使用更像BDD风格的单元测试,就像我在这篇博客文章中解释的那样: http://www.dennisdoomen.net/2010/09/getting-more-out-of-unit-testing-in.html
一般来说,我将这些BDD风格的测试用于本质上非常符合标准的类,以及针对普通类的更多AAA风格的测试。
答案 1 :(得分:1)
[TestFixture]
public class When_Presenter_Loads
{
private MockRepository mockRepository;
private ITableRepository tableRepository;
private IClass clazz;
private Dictionary<string, Type> properties;
private IClassGenerationView view;
private ClassGenerationPresenter presenter;
[SetUp]
public void Setup()
{
mockRepository =new MockRepository();
properties = new Dictionary<string, Type>();
clazz = mockRepository.DynamicMock<IClass>();
view = mockRepository.DynamicMock<IClassGenerationView>();
tableRepository = mockRepository.Stub<ITableRepository>();
}
[Test]
public void View_Should_Display_Class_Properties()
{
using(mockRepository.Record())
{
SetupResult.For(clazz.Properties).Return(properties);
view.ClassProperties = properties;
}
using(mockRepository.Playback())
{
presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
presenter.Load();
}
}
[Test]
public void View_Should_Display_Class_Name_As_A_Table_Name()
{
using (mockRepository.Record())
{
SetupResult.For(clazz.Name).Return("ClassName");
view.TableName = "ClassName";
}
using (mockRepository.Playback())
{
presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
presenter.Load();
}
}
[Test]
public void View_Should_Display_SQL_Data_Types()
{
List<string> dataTypes = new List<string>();
using(mockRepository.Record())
{
SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes);
view.DataTypes = dataTypes;
}
using(mockRepository.Playback())
{
presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
presenter.Load();
}
}
[Test]
public void View_Should_Show_Table()
{
using (mockRepository.Record())
{
SetupResult.For(clazz.Name).Return("ClassName");
view.Table = null;
LastCall.IgnoreArguments();
}
using (mockRepository.Playback())
{
presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
presenter.Load();
}
}
}
我使用了大量的Dynamic mock来测试一个行为。您也可以阅读Dave关于此
的One Mock Per Test文章