鉴于以下方法我可以测试什么以及如何进行测试?
public void DoSomething
{
Get Db record
Update Db the record
Log History in Db
Send an email notification
}
答案 0 :(得分:1)
首先,我同意其他海报,这种方法做得太多了。我个人会让它只做Db的东西,然后我的应用程序层记录操作并发送电子邮件。也就是说,为了对这种方法进行单元测试,我会做以下(在C#中):
首先,给出类在这样的构造函数中存在的类:
public MyClass(
IRepository repository,
ILoggingService loggingService,
INotificationClient notificationClient)
... IRepository
是这样的界面:
interface IRepository
{
Db GetDbRecord();
void UpdateDbRecord(Db record);
}
...... ILoggingService
是这样的:
interface ILoggingService
{
void LogInformation(string information);
}
...而INotificationClient
就像这样:
interface INotificationClient
{
void SendNotification(Db record);
}
在构造函数体中,将传入的参数分配给MyClass
中的私有,只读字段。
接下来,在DoSomething
方法中,从Db
获取IRepository
记录,对其进行更新并将其保存回IRepository
。使用ILoggingService
记录历史记录,然后在SendNotification()
上调用INotificationClient
。
最后,在单元测试中,使用模拟框架(如Moq)来模拟每个接口中的一个。将模拟的对象传递到MyClass
的新实例,调用DoSomething()
,然后验证您的模拟IRepository
是否已被要求更新Db
对象,您的模拟{{1}已经要求我们记录一条消息,并且已经将您的模拟ILoggingService
提交给INotificationClient
。也就是说:
SendNotification()
在运行系统中,您将注入Db record = new Db();
var mockRepository = new Mock<IRepository>();
mockRepository.Setup(r => r.GetDbRecord()).Returns(record);
var mockLoggingService = new Mock<ILoggingService>();
var mockNotificationClient = new Mock<INotificationClient>();
new MyClass(
mockRepository.Object,
mockLoggingService.Object,
mockNotificationClient.Object).DoSomething();
// NUnit syntax:
Assert.That(record["ExpectedUpdatedField"], Is.EqualTo("ExpectedUpdatedValue"));
mockRepository.Verify(r => r.UpdateDbRecord(record), Times.Exactly(1));
mockLoggingService.Verify(ls => ls.LogInformation(It.IsAny<string>()), Times.Exactly(1));
mockNotificationClient.Verify(nc => nc.SendNotification(record), Time.Exactly(1));
'依赖项的正确实现,然后您将在更连贯的对象之间共享责任。
有点啰嗦,但我就是这样做的。)
答案 1 :(得分:0)
对于单元测试 - 您没有“单位”方法。它做了太多事情。为每个单独的作业提取方法并测试这些方法。
通常,单元测试不包括数据库更改等,因此您必须了解如何攻击该部分。它将取决于您使用的框架等。您可以模拟数据库方法并验证您是否正在调用它们。不要去看看数据是否被添加到数据库等。这不是单元测试,你会开始意识到你的测试变得不稳定,速度慢,无法并行化等。
对数据部分进行集成测试/ db测试,并确保回滚您修改的任何数据。还要确保没有测试依赖于其他测试所做的更改。