从单元测试开始,我想知道如何测试我们的旧代码,看起来像这样:
public Player DetermineWinner(Player a, Player b)
{
if(a.Age>b.Age)
....
///few more conditions checking properties of both players
}
class Player
{
public Player (DBConnection c, world w, DateTime logTime)
{} //not easy to mock...
}
如何嘲笑?我知道如果Player实现了一个接口,我可以简单地创建一个mock并在单元测试中将其传递给所需的值,但这不是这里的情况。 Player类是使用各种参数实例化的,所以我不能简单地在单元测试期间创建一个实例并传递它 - 它取决于各种外部对象。 我需要模拟Player对象并同时设置其属性,以便测试是确定性的。开始时最好的方法是什么?
下次我应该使用接口去耦吗?
答案 0 :(得分:1)
你可以通过使用像Typemock这样的框架来对代码进行单元测试,而无需更改代码,这样可以模拟具体的依赖关系而不需要添加接口,当你选择要模拟的类时(在本例中为“Player”,typemock还会自动模拟其中的所有依赖项。)
根据您的例子:
public class UnitTest1
{
[TestMethod]
public void TestDetermineWinner_B_IsTheWinner()
{
var P1 = Isolate.Fake.Instance<Player>();
var P2 = Isolate.Fake.Instance<Player>();
Isolate.WhenCalled(() => P1.Age).WillReturn(0);
Isolate.WhenCalled(() => P2.Age).WillReturn(1);
var result = new ClassUnderTest().DetermineWinner(P1, P2);
Assert.AreEqual(P2, result);
}
}
public class ClassUnderTest
{
public Player DetermineWinner(Player a, Player b)
{
if (a.Age > b.Age) { return a; }
return b;
///few more conditions checking properties of both players
}
}
public class Player
{
public Player(DbConnection c, world w, DateTime logTime)
{ } //not easy to mock...
public int Age { get; internal set; }
}
答案 1 :(得分:0)
我认为你不明白嘲笑的真正含义。
模拟对象与<#34;真实&#34;该类的实现。它只是&#34;看起来&#34;就像那个阶级的对象一样。
但是你(对于模拟框架)可以控制该对象的行为。好吧,除非该字段是私有(请参阅here)。所以:当你的玩家字段不是私密的时候,你就不会有问题。
没有嘲弄框架 - 你真的做不了多少。如果有的话,你可以模拟作为被测试类的构造函数的参数所需的所有对象。
换句话说:最后,你需要一些对象&#34; x&#34;类&#34; X&#34 ;;当使用&#34;真实&#34;上课&#34; X&#34;给你带来很多麻烦,然后你必须用看起来像&#34; X&#34;的东西替换它。
最坏的情况是,你可以有两个不同版本的X类;但这会让事情变得非常复杂。