我在.NET平台上使用Xunit和NMock.我正在测试一个方法是异步的表示模型.该方法创建一个异步任务并执行它,以便该方法立即返回,我需要检查的状态尚未准备好.
我可以在完成时设置一个标志而不修改SUT但这意味着我必须继续检查while循环中的标志,例如,可能超时.
我有什么选择?
我使用NMock2,并且我已经起草了以下NMock类来表示一些常见的模拟框架概念:
Expect:这指定了一个模拟方法应返回的内容,并说必须进行调用或测试失败(当伴随调用时VerifyAllExpectationsHaveBeenMet()).
Stub:this指定模拟方法应返回的内容,但不能导致测试失败.
那我该怎么做呢?
我有一个类API,它具有完整的代码覆盖率,并使用DI来模拟主类函数(Job.Run)中的所有逻辑,它完成所有工作.
我在生产中发现了一个错误,我们没有对其中一个数据输入字段进行验证.
所以,我添加了一个名为ValidateFoo()的存根函数...对这个函数写了一个单元测试来预测一个JobFailedException,运行测试 - 它明显失败,因为该函数是空的.我添加了验证逻辑,现在测试通过了.
太好了,现在我们知道验证工作了.问题是 - 如何编写测试以确保在Job.Run()中实际调用ValidateFoo()?ValidateFoo()是Job类的私有方法 - 因此它不是接口...
无论如何用NMock2.0做到这一点?我知道TypeMock支持非接口类型的假货.但是现在改变模拟库不是一种选择.此时如果NMock不支持它,我只需将ValidateFoo()调用添加到Run()方法并手动测试 - 显然我不想考虑我的Job.Run()方法现在100%覆盖.任何建议?非常感谢,非常感谢.
编辑:我想到的另一个选择是为我的Job.Run功能创建一个集成测试(向它注入复合对象的真实实现而不是模拟).我将为该字段给它一个错误的输入值,然后验证作业失败.这工作并涵盖了我的测试 - 但它不是真正的单元测试,而是测试一个功能单元的集成测试....嗯..
EDIT2:有没有办法做什么?有人有想法吗?也许TypeMock - 或更好的设计?
我有以下方法在HttpResponse对象中写入流.
public HttpResponse ShowPDF(Stream stream)
{
MemoryStream memoryStream = (MemoryStream) stream;
httpResponse.Clear();
httpResponse.Buffer = true;
httpResponse.ContentType = "application/pdf";
httpResponse.BinaryWrite(memoryStream.ToArray());
httpResponse.End();
return httpResponse;
}
Run Code Online (Sandbox Code Playgroud)
为了测试它,我需要恢复处理过的流.有没有办法从httpResponse对象读取流?
我在一个类中有一个公共方法,该类在内部调用该类中的特定私有方法。看起来像这样:
public class MyClass : IMyClassInterface
{
public List<int> MyMethod(int a, int b)
{
MyPrivateMethod(a, b, ref varList, ref someVal);
}
private void MyPrivateMethod(int a, int b, ref List<int> varList, ref double someval)
{
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我基本上想使用NUnit测试此公共方法。我正在使用NMock 2.0进行模拟。我该怎么做?因为,它在内部调用了我不想公开的此私有方法。或者,如果我将私有方法改为protected,有没有办法做到这一点?
我知道有人问过类似的问题,但没有找到明确的解决方案。我正在尝试从一个大类中模拟一个私有字段。私有字段在某些较早的方法中实例化,而我正在尝试对引用该字段的后一种方法进行单元测试。
所以我在课堂上有一个更早的方法:
public bool validateAll(ref DataEntry[] oEntries, string sMediaPlanId, ITemplateGenerator oTempGen)
{
...
// private field that I am trying to mock
this._sMediaPlanObjective = (MPWrapper.Instance).getMediaPlanObjective(sMediaPlanId);
...
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试对引用私有字段的方法进行单元测试:
public bool validateFlightObjective(ref MPDataEntry oEntry)
{
...
string entryFlightObjective = oEntry.getFlightObjective();
string mediaPlanObjective = this._sMediaPlanObjective;
if (entryFlightObjective != mediaPlanObjective)
{
return false;
}
...
return true;
}
Run Code Online (Sandbox Code Playgroud)
鉴于我有一个大类,而这只是我要测试的一种方法,是否有可能仅模拟此私有字段的方法?我是缺少基本的东西还是应该考虑其他方法?
我有一个简短的问题,我在关于NMock2.0的文档中无法弄清楚.
我有一个名为Save()的函数,我想模拟出来.这将字符串ID作为参数,小数作为值.
我知道我可以编写这个来确保使用2个特定值调用Save():
Expect.Once.On(dao) _
.Method("Save").With(New Object() {"foo", 1})
Run Code Online (Sandbox Code Playgroud)
但是只有当"foo"和1通过时,这才会通过.我确实控制了值"foo",但对于第二个值,我不知道它会是什么; 或者我不关心测试它至少在这个特定测试中的价值.
我知道我可以写:
Expect.Once.On(dao) _
.Method("Save").WithAnyArguments()
Run Code Online (Sandbox Code Playgroud)
但这将允许我通过任何辩论; 因此,如果保存界面更改,稍后需要5个参数,我的测试仍将通过.
我怎样才能确保它只需要2个参数,并且它们的类型合适?
也许更重要的是 - 写这样的单元测试太脆了?也许我应该编码它以期待任何参数,所以每次重构我都不必回来改变那条线?我发现我使用大量模拟的测试用例非常脆弱,无论何时我重构我都要改变它们......也许我在这里使用模拟错误?这个东西还是很新的,所以任何建议都非常感谢.
我有一个像这样的方法:
public string MyMethod(string a, string b)
{
if(a == "abcd" && b == "xyz")
return "good";
if(a == "xyz" && b == "something")
return "even better";
return "unexpected";
}
public string MainMethod()
{
string s1, s2;
if(some condition)
{
s1= "abcd";
s2 = "xyz";
}
return service.MyMethod(s1, s2);
}
Run Code Online (Sandbox Code Playgroud)
我的模拟对象是这样创建的
AppObj obj = new AppObj();
Mockery mocks = new Mockery();
mockMyService = mocks.NewMock<IMyService>();
Expect.Once.On(mockMyService ).Method("MyMethod").
With("abcd", "xyz").
Will(Return.Value("good"));
obj.MainMethod();
Expect.Once.On(mockMyService ).Method("MyMethod").
With("xyz", "something").
Will(Return.Value("even better"));
obj.MainMethod();
Run Code Online (Sandbox Code Playgroud)
上面代码的问题是,它总是需要第一个模拟方法的参数并返回"good".我需要做些什么才能使NMock为具有不同参数值的相同方法返回不同的值?请帮忙!!
这是一个针对线程迷的人.我有这个方法:
public void RefreshMelts()
{
MeltsAvailable.Clear();
ThreadPool.QueueUserWorkItem(delegate
{
Dispatcher.BeginInvoke((ThreadStart)delegate
{
eventAggregator.GetEvent<BusyEvent>().Publish(true);
eventAggregator.GetEvent<StatusMessageEvent>().Publish(
new StatusMessage("Loading melts...", MessageSeverity.Low));
});
try
{
IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();
Dispatcher.Invoke((ThreadStart)delegate
{
foreach (MeltDto availableMelt in meltDtos)
{
MeltsAvailable.Add(availableMelt);
}
OnPropertyChanged("MeltsAvailable");
eventAggregator.GetEvent<BusyEvent>().Publish(false);
eventAggregator.GetEvent<StatusMessageEvent>().Publish(
new StatusMessage("Melts loaded", MessageSeverity.Low));
});
}
catch (ApplicationException ex)
{
log.Error("An error occurred in MeltsViewModel when attempting to load melts", ex);
Dispatcher.Invoke((ThreadStart)delegate
{
MeltsAvailable.Clear();
eventAggregator.GetEvent<StatusMessageEvent>().Publish(
new StatusMessage("Melt data could not be loaded because an error occurred; " +
"see the application log for detail", …Run Code Online (Sandbox Code Playgroud) 我刚开始使用NMock进行单元测试
我的一个测试案例涉及在字典中添加一个条目,然后将其传递给正在测试的单元.我将地图定义为:
var item = new Mock<MyClass>().Object;
var myMap = new Dictionary<MyClass, IList<MyOtherClass>>
{
{ item, completionRequirement }
};
Run Code Online (Sandbox Code Playgroud)
但是,当我myMap.ContainsKey(item)在被测试的单元内部进行返回时false.
我可以在字典中查看代理项目以检查它.我猜我还需要在模拟上做其他事情item.(最有可能定义.Equals(object o)).
我的问题是:
item.我有这个:
Expect.Once.On( someObj ).Method( "SomeMethod" )
.With(1) // correct value is 2, I want this to fail
.Will( Throw.Exception( new Exception() ) );
Run Code Online (Sandbox Code Playgroud)
当nmock检测到我输入1而不是2时,会抛出异常.但是,测试失败(红色)而不是传递.即使我期待例外,如何使这个测试通过?
nmock ×11
c# ×6
unit-testing ×6
mocking ×4
.net ×2
tdd ×2
.net-2.0 ×1
asp.net ×1
dispatcher ×1
expect ×1
httpresponse ×1
moq ×1
nmock2 ×1
nunit ×1
return-value ×1
rhino-mocks ×1
stub ×1
testing ×1
typemock ×1
wpf ×1
xunit.net ×1