我试图了解单元测试的某些方面,所以我创建了一个简单的解决方案,具有以下架构:
在Business层中,我创建了一个实现IFizzBuzz接口的FizzBuzz类(FizzBuzzService)。
namespace SampleApp2017.Business
{
public class FizzBuzzService : IFizzBuzz
{
public bool IsFizzBuzz(int num)
{
if (num % 3 == 0 || num % 6 == 0)
{
return true;
}
else
{
return false;
}
}
public bool IsFizz(int num)
{
return (num % 3 == 0 ? true : false);
}
public bool IsBuzz(int num)
{
if (num % 6 == 0)
{
return true;
}
else
{
return false;
}
}
}
}
(以下是接口详情以供参考)
namespace SampleApp2017.Business
{
public interface IFizzBuzz
{
bool IsFizzBuzz(int num);
bool IsFizz(int num);
bool IsBuzz(int num);
}
}
在此示例解决方案中,WebUI和ConsoleApp都使用依赖注入来使用FizzBuzz服务,我理解为什么这是必要的,但是当涉及单元测试服务时我感到困惑。
以下是我为FizzBuzz方法设置的测试:
[TestMethod]
public void fizzbuzz_should_return_true()
{
//Arrange
//Bring in the business rules
IFizzBuzz _fbservice = new FizzBuzzService();
//Act
/// Send 12 to service, should return true
bool resultof12 = _fbservice.IsFizzBuzz(12);
//Assert
Assert.AreEqual(resultof12, true);
}
我现在正在寻找关于运行单元测试的“最佳实践”的一些指导。
在单元测试中,我是否需要编程到接口?会出现什么问题:
FizzBuzzService _fbservice = new FizzBuzzService();
最后,如果我想在这个例子中模拟,它会在哪里出现,有什么优势?
答案 0 :(得分:1)
我认为测试这个类的实际实现会更好。它向其他读者/开发者提供关于您的测试的明确信息
FizzBuzzService _fbservice = new FizzBuzzService(); // better then IBuzzService
在当前示例中,您根本不需要Mock。因为你的班级没有其他依赖性 当您需要提供某些依赖项的结果时使用Mocks,这些依赖项的逻辑不属于当前测试的一部分 模拟可以作为构造函数参数传递,也可以作为方法参数传递或作为当前类的属性传递。
回复关于嘲笑的评论:
您需要Mock,因为不与数据库交互。单元测试必须快速,如果不快,开发人员将无法运行它们。因此,您不希望您的单元测试与数据库或其他IO设备进行通信
你不是事件需要模拟框架 - 你可以通过实现具有测试逻辑的接口来创建自己的模拟
public interface IUserDataService
{
User GetById(int id);
}
public class BonusCalculator
{
private readonly IUserdataService _dataService;
public BonusCalculator(IUserDataService dataService)
{
_dataService = dataService;
}
public int CalculateBonusForUser(int userId)
{
const int BONUS = 100;
var deservedBonus = 0;
var user = _dataService.GetById(userId);
if (user.IsDeservedBonus)
{
deservedBonus += BONUS;
}
return deservedBonus;
}
}
现在你要测试一下,如果UserDataService返回的用户应得的奖励返回值将等于100.
因此,您可以创建GetById
public class FakeUserDataService : IUserDataService
{
public User DummyUser { get; set; }
public User GetById(int id) => DummyUser;
}
然后你可以测试CalculateBonusForUser
的逻辑而不用担心用户如何返回,因为这不关心这个类
public void CalculateBonusForUser_ShouldReturn100_WhenUserIsDeservedEqualsTrue()
{
var user = new User { IsDeserved = true };
var fakeDataService = new FakeUserDataService { DummyUser = user };
var calculator = new BonusCalculator(fakeDataService);
var actualBonus = calculator.CalculateBonusForUser(1);
Assert(actualBonus, 100);
}