我正在尝试测试一个方法,该方法有一个using语句,用于创建IDisposable类型的新具体实例。
为此,我试图伪造一个在IDisposable类型的构造函数中执行的私有方法。 我可以更改代码,以便更容易测试,但我想知道这种方式是否可行。
到目前为止,我有:
说明我的问题的示例代码
namespace FakeUsing
{
using System;
using System.Linq.Expressions;
using System.Runtime.Remoting.Messaging;
using FakeItEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
// Application under test
class Program
{
public bool success = false;
// Entry Point
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
// Method I would like to test
public void Run()
{
using (new Concrete("data"))
{
// Code I actually want to test.
success = true;
}
}
}
// Problem class that I cannot change
public class Concrete : IDisposable
{
public Concrete(string data)
{
PrivateCall();
}
private void PrivateCall()
{
// Some stuff that uses unmanaged resources
// I'm not interested in testing
DoStuff();
}
public void Dispose()
{
// Some stuff that uses unmanaged resources
// I'm not interested in testing
DoStuff();
}
private void DoStuff()
{
throw new NotImplementedException();
}
}
// Testing code
[TestClass]
public class UnitTests
{
[TestMethod]
public void TestRun()
{
// Arrange
Program p = new Program();
MethodInfo doStuffMethodInfo =
typeof(FakeUsing.Concrete)
.GetMethod("DoStuff", BindingFlags.Instance | BindingFlags.NonPublic);
// This is the line I cannot get to work.
MethodCallExpression doStuffMCE =
Expression.Call(???, doStuffMethodInfo, null);
A.CallTo(doStuffMCE).DoesNothing();
// Act
p.Run();
// Assert
Assert.IsTrue(p.success);
}
}
}
在FakeUsing.UnitTests.TestRun中,我无法绕过创建MethodCallExpression实例,因为我手头没有实例。
由于
大卫
答案 0 :(得分:2)
这是不可能的。 FakeItEasy只能拦截它创建的伪造方法,并且你new
生产类进行测试。
即使有可能,我也会反对。模拟private
方法通常会导致(最多)过度指定的脆弱测试。一旦实施发生变化,所有测试都会中断。如果(正如您提示的那样),您无法控制具有私有方法的类,这尤其危险。
我认为更好的方法是更改生产代码(您可以更改)以使用某种工厂返回IDisposable
。然后提供返回无操作对象的工厂实现。使用FakeItEasy时,这应该非常简单。 (或者甚至没有它!行为很简单,如果你还没有,你就不需要一个模拟框架。)