简体   繁体   English

根据私有方法测试公共方法的方法

[英]Approach to test public methods depending on private methods

I'm trying to add tests to a legacy code, and as I start to adding code, I get the feeling that something is wrong. 我正在尝试将测试添加到遗留代码中,当我开始添加代码时,我感觉有些问题。

In the following code, the public method RegisterChange is calling two private methods to: 在下面的代码中,公共方法RegisterChange正在调用两个私有方法:

  1. Get the object to store 获取要存储的对象
  2. Store the object 存储对象
public class ChangeService {

    IRepository repository;

    public ChangeService(IRepository repository){
        this.repository = repository;
    }

    public bool RegisterChange( int entityId ){ 
        var entity = GetParsedEntity( entityId );       
        SaveEntity( entity );
        return true;
    }

    private Entity GetParsedEntity( int id ) {
        var entity = repository.GetEntityById( id );
        return new Entity{ Name = entity.Name };
    }

    private void SaveEntity( Entity entity ) {
        repository.Save( Entity );
    }
}

public class ChangeServiceFact(){

    [Fact]
    public void When_valid_entity__Should_save_entity(){

        var mock = new Mock<IRepository>();
        var service = new ChangeService(mock.object);

        var result = service.RegisterChange( 0 );

        Assert.True(result);
    }   
}

So, when Im mocking the repository, I had to go and check the private method's code to know which operations to mock. 因此,当Im模拟存储库时,我不得不去检查私有方法的代码以了解要模拟的操作。

The problem that I'm seeing with this approach is that, because the code is testing not only the test subject (the public method) but also the private methods, is not clear which should be the test result by looking at the test subject (public method). 我用这种方法看到的问题是,因为代码不仅测试测试主题(公共方法)而且还测试私有方法,因此通过查看测试主题不清楚哪个应该是测试结果(公共方法)。

In the case that, later on, someone decide to modify one private method (like throwing an exception from GetParsedEntity), the test will continue to pass correctly, but the client code could fail because of this change. 在稍后有人决定修改一个私有方法(比如从GetParsedEntity抛出异常)的情况下,测试将继续正确传递,但客户端代码可能因此更改而失败。

In this particular case, Im using C#, XUnit and Moq, but I think is more a general testing question. 在这种特殊情况下,我使用C#,XUnit和Moq,但我认为这更像是一个常见的测试问题。

The problem that I'm seeing with this approach is that, because the code is testing not only the test subject (the public method) but also the private methods, is not clear which should be the test result by looking at the test subject (public method). 我用这种方法看到的问题是,因为代码不仅测试测试主题(公共方法)而且还测试私有方法,因此通过查看测试主题不清楚哪个应该是测试结果(公共方法)。

The test subject you mention has no visible effect without knowing its full contract. 你提到的测试对象在不知道完整合同的情况下没有明显效果。 What the full contract here is? 这里的完整合同是什么? The mentioned public method and constructor, which takes dependency. 提到的公共方法构造函数,它具有依赖性。 It's the dependency that's important here and interaction with this dependency is what should be tested. 这是依赖,这是重要的,与这种依赖的交互是应该测试的。 Private methods are (as always) implementation detail - irrelevant to unit testing . 私有方法(一如既往)实现细节 - 与单元测试无关

Having said that, let's get back to the contract. 话虽如此,让我们回到合同中。 What is the actual contract of test subject ( ChangeService method)? 什么是测试主题的实际合同( ChangeService方法)? To retrieve object from repository basing on some id, create different object and save the later in the same repository. 要基于某个id从存储库中检索对象,请创建不同的对象并将后者保存在同一个存储库中。 And this is your test. 这是你的考验。

[Fact]
public void ChangeService_StoresNewEntityInRepository_BasedOnProvidedId()
{
    const string ExpectedName = "some name";
    var otherEntity = new OtherEntity { Name = ExpectedName };
    var mock = new Mock<IRepository>();
    var service = new ChangeService(mock.object);
    mock.Setup(m => m.GetEntityById(0)).Return(otherEntity);

    service.RegisterChange(0);

    mock.Verify(m => m.SaveEntity(It.Is<Entity>(e => e.Name == ExpectedName));
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM