如何对使用 PetaPoco.Database 的服务进行单元测试

Posted

技术标签:

【中文标题】如何对使用 PetaPoco.Database 的服务进行单元测试【英文标题】:How to unit test service that is using PetaPoco.Database 【发布时间】:2012-06-01 18:18:05 【问题描述】:

我在当前项目中使用PetaPoco 作为微型 ORM,我必须说我喜欢它。但是,我发现自己在使用 PetaPoco.Database

的简单场景中苦苦挣扎
public class MyService : IMyService

    private readonly PetaPoco.Database _database;

    public MyService(PetaPoco.Database database)
    
        _database = database;
    

    public void SaveSomething(MyObject myObject)
    
        //...custom logic
        _database.Save(myObject);
    

我正在使用 IoC (Castle.Windsor) 在需要的地方注入 IMyServicePetaPoco.Database

现在,当我尝试对我的服务进行单元测试时,我无法正确模拟存根 PetaPoco.Database 以验证 Save 方法是否被正确调用。 我正在使用 NUnitRhino.Mocks 进行单元测试和模拟。

[TestFixture]
public class MyServiceTests
 

    private PetaPoco.Database _database;

    [SetUp] 
    public void SetUp()
    
        _database = MockRepository.GenerateMock<Database>("");
    

    [Test]
    public void ShouldProperlySaveSomething()
    
        //Arrange
        var myObject = new MyObject();
        _database.Expect(db => db.Save(Arg<MyObject>.Is.Anything));
        var myService = new MyService(_database);

        //Act
        myService.SaveSomething(myObject);

        //Assert
        _database.VerifyAllExpectations();   
    


我知道,如果我从 PetaPoco.Database 中提取一个接口并对其进行模拟,或者通过虚拟化我想要模拟的 PetaPoco 方法,可以解决这个问题,但重点是我根本不想对 PetaPoco 进行更改。

这可行吗?

【问题讨论】:

【参考方案1】:

我的分支位于此处:https://github.com/schotime/PetaPoco 已经为 Database 类定义了一个接口。

还有我的新 Fork https://github.com/schotime/NPoco 或 NPoco on nuget 具有相同的 api。

我会使用其中之一。 ;)

【讨论】:

干得好@Schotime,这正是我所需要的!不过我很好奇,您是否尝试过向原始代码库创建拉取请求? 很多时候,但我现在有更多功能作为库的一部分,并修复了很多错误,因此它们现在几乎是两个独立的。 是否支持 petapoco 的所有功能(例如模板)或缺少东西?看起来你的叉子也做了这个插件所做的 PetaPoco.RelationExtensions。您是否使用相同的代码?我想知道您没有看到关于您的某些功能的任何文档,因此希望我可以使用其他现有插件的示例。 @chobo2 你需要什么文件?我在这里开始了一些:github.com/schotime/NPoco/wiki 我没有看到额外部分中任何项目的任何文档。【参考方案2】:

您已经使用 IMyService 交互抽象了与 PetaPoco.Database 的交互,那么为什么还需要另一个抽象呢?使用您当前的方法,您应该能够使用 IMyService 测试与数据库的交互,例如

public class AuthenticationService 

    private IMyService myService;

    public AuthenticationService(IMyService service) 
    
        ...
    

    public void Authenticate(string username, string password)
    
       var user = myService.GetUser(username); // <-- Hits the database
    

要测试它,您只需使用 IMyService 的模拟/存根模拟交互。

现在关于您的原始解决方案,如果 PetaPoco 公共方法不是虚拟的,我会分叉它,修复代码并向他们发送拉取请求。否则,我觉得你的方法很好。

【讨论】:

感谢您的回答@Hadi。我问这个问题的关键在于我想单独测试 MyService 业务逻辑,即我不想访问数据库,同时我想确保数据库调用是通过 PetaPoco 触发的。在我看来,这只能通过模拟 PetaPoco.Database 来实现。 分叉代码,另一方面,对我来说似乎是一个很好的解决方案,我可能会尝试一下。

以上是关于如何对使用 PetaPoco.Database 的服务进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 scikit-learn 对文本对进行分类?

如何对函数的输出使用索引? [复制]

如何使用按钮使用 JavaScript 对数组进行计数?

如何使用 JMeter 对 Websocket 进行负载测试?

中文情感分类任务如何对bert语言模型微调,微调后的模型如何使用

如何使用 SVM 对图像进行分类