RhinoMocks的意外行为:
var mocks = new MockRepository();
var connection = mocks.Stub<OracleConnection>();
var command = mocks.Stub<OracleCommand>();
using (mocks.Record()) {
connection.Expect(x => x.CreateCommand()).Return(command);
command.Expect(x => x.ExecuteNonQuery());
command.Expect(x => x.Dispose());
}
using (mocks.Playback()) {
using(var command = connection.CreateCommand()) {
...
command.ExecuteNonQuery();
}
}
尽管我已经预料到Dispose() - Call,但它无法识别,我收到以下消息:
Rhino.Mocks.Exceptions.ExpectationViolationException: IDisposable.Dispose(); Expected #0, Actual #1.
如果我在没有using子句的情况下重新编写代码,一切都很好:
OracleCommand cmd = null;
try {
command = connection.CreateCommand();
...
command.ExecuteNonQuery();
}
finally {
if (command != null)
command.Dispose();
}
关于这个问题的任何想法?
此致 的MacX
答案 0 :(得分:2)
This question and answer表明问题可能源于您正在查找OracleCommand
,而不是IDbCommand或类似内容。
对已接受答案的评论表明,如果OracleCommand
是抽象类,则应使用GeneratePartialMock<OracleCommand>()
进行嘲弄。
我希望这会对你有所帮助。
在回复您的评论时,听起来您需要OracleCommand
的特定于实现的方法,但无法正确模拟它。
虽然OracleCommand
已被密封,但您可以合成地将其包裹起来。它需要一些工作,但允许您在代码中使用OracleCommand
并在测试中模拟它。
public interface IOracleCommand : IDbCommand
{
void OracleMethod();
string OracleProperty { get; set; }
}
public class OracleCommandWrapper : IOracleCommand
{
private OracleCommand _inner;
public OracleCommandWrapper(OracleCommand inner)
{
_inner = inner;
}
public void Dispose()
{
_inner.Dispose();
}
public IDbDataParameter CreateParameter()
{
return _inner.CreateParameter();
}
// do this for all the members, including the Oracle-specific members
public void OracleMethod()
{
_inner.OracleMethod();
}
public string OracleProperty
{
get { return _inner.OracleProperty; }
set { _inner.OracleProperty = value; }
}
}
现在,您可以在代码中使用IOracleCommand
和OracleCommandWrapper
,在测试中,您只需模拟或存根IOracleCommand
界面。
同样,它需要一些腿部工作,但能让你到达目的地。