[英]Unit Testing of a static factory method containing logic
before I begin with my question I want to point out that I am aware that there are tons of similar questions on stack overflow. 在开始我的问题之前,我想指出的是,我知道在堆栈溢出中有很多类似的问题。 Unfortunately none of these questions helped me finding a good solution in my concrete scenario.
不幸的是,这些问题都没有帮助我在具体情况下找到好的解决方案。
The Problem: 问题:
I want to write a unit test for a static factory method which contains logic. 我想为包含逻辑的静态工厂方法编写单元测试。 I am looking for a way to unit test this method even if it is static.
我正在寻找一种对该方法进行单元测试的方法,即使它是静态的。 If that is not possible maybe someone can point out a better design for my class under test.
如果这不可能,那么也许有人可以为我正在测试的班级指出更好的设计。 I also considered using IoC but couldn't see the advantage considering unit-testing.
我也考虑过使用IoC,但是在考虑单元测试时看不到优势。
The Code: 编码:
public class Db
{
private XmlMapping mapping;
public static Db<T> Create()
{
var mapping = XmlMapping.Create(typeOf(T).Name);
return new Db(mapping);
}
private Db(XmlMapping mapping)
{
this.mapping = mapping;
}
}
public class XmlMapping //class under test
{
public static XmlMapping Create(string filename) //method under test
{
try
{
ValidateFilename(filename);
//deserialize xml to object of type XmlMapping
var result = Deserialize(filename);
if (result.IsInValid())
throw Exception()
return result;
}
catch (Exception)
{
throw new DbException();
}
}
}
The method Create which I want to unit test is within the class XmlMapping . 我要进行单元测试的Create方法在XmlMapping类中。 This method serializes a xml file and generates an object of type XmlMapping.
此方法序列化xml文件并生成XmlMapping类型的对象。 I tried to write a stub for the serialization part.
我尝试为序列化部分编写存根。 But didn't want to call my Database Factory with a Mapping class in the constructor (constructor injection).
但是不想用构造函数中的Mapping类调用我的数据库工厂(构造函数注入)。
Edit: 编辑:
My database factory is generic. 我的数据库工厂是通用的。 The generic type is used to figure out which xml file should be louded ie: typeOf(T) = Customer --> XmlMapping-File = Customer.xml
通用类型用于确定应该大声显示哪个xml文件,即: typeOf(T)= Customer-> XmlMapping-File = Customer.xml
The Solution (Thx to Jeff!): 解决方法(谢谢杰夫!):
public class XmlMapping : IMapping //class under test
{
internal static Func<Type, IMapping> DeserializeHandler { get; set; }
static XmlMapping()
{
DeserializeHandler = DeserializeMappingFor;
}
public static IMapping Create(Type type)
{
try
{
var mapping = DeserializeHandler(type);
if (!mapping.IsValid())
throw new InvalidMappingException();
return mapping;
}
catch (Exception ex)
{
throw new DataException("Failed to load mapping configuration from xml file.", ex);
}
}
internal XmlMapping(IMapping mapping)
{
this.Query = mapping.Query;
this.Table = mapping.Table;
this.Entity = mapping.Entity;
this.PropertyFieldCollection = mapping.PropertyFieldCollection;
}
private XmlMapping() { }
}
[TestClass]
public class MappingTests //testing class
{
[TestMethod]
public void Create_ValidDeserialization_ReturnsObjectInstance()
{
XmlMapping.DeserializeHandler = MakeFakeHandlerFor(MakeMappingStub());
var result = XmlMapping.Create(typeof(ActivityDto));
Assert.IsInstanceOfType(result, typeof(XmlMapping));
}
}
I would use a fake action handler to assist in verifying the content of the call to deserialize. 我将使用伪造的动作处理程序来帮助验证反序列化调用的内容。 Let's add a Func delegate property and default that to your serialize method.
让我们添加一个Func委托属性,并将其默认设置为您的序列化方法。 Your XmlMapping class and test would like something like:
您的XmlMapping类和测试将类似于:
public class XmlMapping //class under test
{
static XmlMapping()
{
// Default the handler to the normal call to Deserialize
DeserializeHandler = Deserialize;
}
public static XmlMapping Create(string filename) //method under test
{
//deserialize xml to object of type XmlMapping
//preudocode:
var result = DeserializeHandler(string.Format("{0}.xml",filename));
//...
return result;
}
// Abstract indirection function to allow you to swap out Deserialize implementations
internal static Func<string, XmlMapping> DeserializeHandler { get; set; }
private static XmlMapping Deserialize(string fileName)
{
return new XmlMapping();
}
}
public class CreateTests {
public void CallingDeserializeProperly()
{
// Arrange
var called = false;
Func<string, XmlMapping> fakeHandler = (string f) =>
{
called = true; // do your test of the input and put your result here
return new XmlMapping();
};
// Act
XmlMapping.DeserializeHandler = fakeHandler;
var m = XmlMapping.Create("test");
// Assert
Assert.IsTrue(called);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.