我对工厂方法的单元测试有疑问。 假设我们有以下代码,并想测试Foo.ToBar方法。
class Bar
{
public Bar(int someparam)
{
}
}
class Foo
{
int m_someprivate;
public Foo()
{
m_someprivate = 1;
}
public Bar TooBar()
{
return new Bar(m_someprivate);
}
}
我看到了两种不同的方法。其中一个将是那样的
[Test]
void TooBarTest()
{
Foo foo = new Foo();
Bar result = foo.TooBar();
Assert.AreEqual(new Bar(1), result);
}
这是非常直截了当的。但是,我不喜欢它有两个原因
a)我们在测试Foo类时无意中测试了Bar类的一部分。例如,如果Bar构造函数抛出,那么我们的测试将失败,这是错误的,因为 Foo类很好。这是一个有问题的Bar类。
b)我不喜欢Assert new Bar(1)中使用的生产代码。我宁愿使用某些常量而不是某些代码 例如,取决于某些外部状态(等),可能会返回不同的结果。
我看到的另一种方法是基于独立工厂的创建,它将创建Bar
class Bar
{
public Bar(int someparam)
{
}
}
interface IBarFactory
{
Bar create(int someparam);
}
class BarFactory : IBarFactory
{
public Bar create(int someparam)
{
return new Bar(someparam);
}
}
class Foo
{
int m_someprivate;
BarFactory m_barFactory;
public Foo()
{
m_someprivate = 1;
m_barFactory = new BarFactory();
}
public Bar TooBar()
{
return m_barFactory.create(m_someprivate);
}
public void setBarFactory(BarFactory barFactory)
{
m_barFactory = barFactory;
}
}
[Test]
void TooBarTest()
{
Mockery mockery = new Mockery()
IBarFactory barFactoryMock = mockery.NewMock<IBarFactory>();
Expect.Once.On(barFactoryMock).Method("create").With(new Object[] { 1 }).Will(Return.Value(new Bar(1));
Foo foo = new Foo();
foo.setBarFactory(barFactoryMock);
foo.ToBar();
}
看起来这是更好的方式。但是,我不喜欢我们必须创建工厂接口,工厂,工厂设置器并使测试更复杂,只需测试1行代码。
你对此有何看法?你喜欢哪个?你有其他测试方法吗?
答案 0 :(得分:4)
我与Tomas Jansson结盟。此外,我会在构造函数中注入IBarFactory,而不是实例化BarFactory。因此,您永远不必触摸Bar和BarFactory。相反,您可以在测试时将IBarFactory存根。
答案 1 :(得分:3)
我肯定会选择独立的工厂方法。另外,我会将方法的名称从ToBar
更改为其他名称。