我有以下代码:
public FuzzyPickles(IPie pieMaker)
{
_pieMaker = pieMaker;
}
public string PieName
{
get
{
if (_pieName == null)
{
GetPieName();
}
return _pieName;
}
}
private async void GetPieName()
{
string asyncPieName = string.Empty;
try
{
var task = _pieMaker.GetDeliciousPieAsync();
asyncPieName = await task;
}
catch (RottenFruitException e)
{
Debug.Write(e.Message);
}
if (!string.IsNullOrEmpty(asyncPieName))
{
_pieName = asyncPieName;
NotifyPropertyChanged(PieName);
}
}
我想编写一个测试(我正在使用 RhinoMocks)来验证在该 getter 中抛出的异常不会让我得到带有腐烂水果的馅饼:
[TestClass]
public class FuzzyTest
{
private FuzzyPickles _pickles;
private IPie _pieMocker;
[TestInitialize]
public void Setup()
{
_pieMocker = MockRepository.Mock<IPie>();
_pickles = new FuzzyPickles(_pieMocker);
}
[TestMethod]
public void PieName_WhenGettingException_ShouldHandleExceptionGracefully()
{
_pieMocker.Stub(x => x.GetDeliciousPieAsync()).Throws(new RottenFruitException());
var pieName = _pickles.PieName;
//What should I assert here ?
}
}
现在这是我真正的问题。
删除 try/catch block 不会将异常抛回给 UT 运行器,因为我没有在 UT 中使用 await,因为它没有原型(prototype)化为异步任务并且 getter 不能异步,因此我不能等待或使用函数相反(或者我可以吗?)
那个 getter 绑定(bind)到 UI(即:我用它来在我的 UI 中显示信息,所以我不知道什么时候 - 如果有的话 - 它会被调用),这就是我做这个丑陋功能的原因调用 hack,并在其中使用 NotifyPropertyChanged(这里我们不要担心跨线程异常,这不是重点)
我不想使用隐藏代码(Windows Phone 8.1/Silverlight 项目)。
如果删除 try/catch block ,我该如何编写一个会失败的单元测试?我应该断言什么?
最佳答案
由于属性不兼容 async
(这是 IMO 的明智设计选择),您可以采用 Stephan Clearys blog post 中提到的 IntializeXXXAsync
模式.
该模式的作用是让您调用负责创建值的初始化方法。如果失败,您可以默认返回到 default(T)
,在您的字符串情况下它只是 null
,并对其断言:
public class FuzzyPickles : INotifyPropertyChanged
{
public FuzzyPickles(IPie pieMaker)
{
_pieMaker = pieMaker;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
private string _pieName;
public string PieName
{
get
{
return _pieName;
}
private set
{
_pieName = value;
OnPropertyChanged()
}
}
public async Task InitializePieAsync()
{
string asyncPieName = string.Empty;
try
{
PieName = await _pieMaker.GetDeliciousPieAsync();
}
catch (RottenFruitException e)
{
Debug.Write(e.Message);
}
}
}
现在初始化 FuzzyPickles
,初始化并断言它不为空:
[TestMethod]
public async Task PieName_WhenGettingException_ShouldHandleExceptionGracefully()
{
_pieMocker.Stub(x => x.GetDeliciousPieAsync()).Throws(new RottenFruitException());
await _pickles.InitializePieAsync();
var pieName = _pickles.PieName;
Assert.IsNotNull(pieName);
}
关于c# - 单元测试在 try catch block 中调用异步操作的 getter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25751378/