我想为其他人编写的程序编写测试。但是在编写测试时我遇到了一些问题。我无法准确理解如何伪造一些物体。我搜索并找到了Unit Test for n tier architecture,但它对我没有帮助。例如,我想为下面的代码编写一个测试(我知道这是一个虚拟代码,只是为了澄清)
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
DAL customerDal = new DAL();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
我只想测试FetchCustomersByName但是与DAL有连接。我认为创建存根类但在这种情况下我必须更改我的原始代码。它由其他人编码。我该如何为这种方法编写测试?
提前致谢。
答案 0 :(得分:1)
不要对数据访问层进行单元测试。为它编写集成测试。
在DAL中模拟依赖项并不值得给它带来麻烦,因为它不能保证任何东西。
如果你考虑一下,DAL依赖于SQL方言和数据库模式。因此,您的单元测试可能会正常工作。但是当你运行真正的解决方案时,它仍然会失败。原因可能是您的SQL查询不正确或者其中一个类属性类型与表列类型不匹配。
单元测试通常是针对业务逻辑编写的。他们捕获的一件事是不会产生异常的错误,例如错误的条件或计算错误。
<强>更新强>
确定。所以你的例子实际上包含业务逻辑。方法名称欺骗了我。
您必须更改创建DAL类的方式。但你不必像杰克休斯所说的那样使用构造函数注入。相反,您可以使用工厂模式:
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
var customerDal = DalFactory.Create<CustomerDal>();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
这更简单,因为现在您可以使用“全部替换”将所有var customerDal = new CustomerDal()
更改为var customerDal = DalFactory.Create<CustomerDal>();
在该工厂类中,您可以调用不同的实现
public class DalFactory
{
public static IDalFactory Factory { get set; }
static DalFactory()
{
Factory = new DefaultDalFactory();
}
public static T Create<T>() where T : class
{
return Factory.Create<T>();
}
}
public interface IDalFactory
{
T Create<T>() where T : class
}
public class DefaultDalFactory : IDalFactory
{
public T Create<T>() where T : class
{
return new T();
}
}
代码不漂亮,但它以最小的重构解决了你的问题。我建议你从那开始,然后尝试改变你的编码标准,以便允许构造函数注入。
要在测试中使用它,您可以使用以下实现。它使用[ThreadStatic]允许多个测试同时运行。
public class TestDalFactory : IDalFactory
{
[ThreadStatic]
private static Dictionary<Type, object> _instances;
public static Dictionary<Type, object> DalInstances
{
get
{
if (_instances == null)
_instances = new Dictionary<Type, Object>();
return _instances;
}
}
public static TestDalFactory Instance = new TestDalFactory();
public T Create<T>() where T : class
{
return (T)_instances[typeof(T)];
}
}
接下来,在测试中,您可以通过执行以下操作配置DAL工厂以返回模拟:
[TestClass]
public class MyBusinessTests
{
[TestInitialize]
public void Init()
{
DalFactory.Instance = TestDalFactory.Instance;
}
[TestMethod]
public void do_some_testing_in_the_business()
{
TestDalFactory.Instance.DalInstances[typeof(CustomerDal)] = new MyNewMock();
//do the testing here
}
}
答案 1 :(得分:1)
使用构造函数注入DAL将允许您存根DAL层。理想情况下,您将注入一个接口。使用我使用的工具来模拟具体类是有点痛苦的。商业模拟工具可能更适合模拟具体类,但我没有使用任何这些。
class YourClass
{
private DAL customerDal;
public YourClass(DAL theDal)
{
customerDal = theDal;
}
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
// don't create the DAL here...
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
}
[Test]
public void TestMethodHere()
{
// Arrange
var dalMock = Mock.Of<DAL>();
// setup your mock DAL layer here... need to provide data for the FetchByName method
var sut = new YourClass(dalMock);
// Act
var actualResult = sut.FetchCustomersByName(new CustomerObject());
// Assert
// Your assert here...
}