如何使用NSubstitute模拟受保护的方法

时间:2016-02-17 21:53:46

标签: c# unit-testing object mocking nsubstitute

public static void Mock(out IProgram prog, out IJson json)
{    
    prog = Substitute.For<IProgram>();
    IJson = Substitute.For<IJson>();

    prog.SaveProg(1, 1, 1, "Somthing", 1, DateTime.UtcNow,
                 (DateTime.UtcNow + TimeSpan.FromDays(10)), 
                 10, "someemail@email.com", DateTime.UtcNow, 1)
        .Returns(ObjectResult<int?>); 
}

我在调用Returns(ObjectResult<int?>)时收到错误,因为ObjectResult是受保护的类。我如何解决这个问题,以便能够从实际方法中调用我的模拟方法?

2 个答案:

答案 0 :(得分:3)

您不应模拟受保护的类/方法。

但是您实际上可以! (至少对于方法和属性而言)

NSubstitute在调用某个替代方法后会覆盖该方法的行为,但实际上并不关心您如何调用该方法。这样可以通过反射调用它。

下面是一个非常详细的示例:

public class SomeRepository
{
    public string ReadData() => ActuallyPerformDataReading();
    protected virtual string ActuallyPerformDataReading() => "some wrong data";
}

public class SomeClass
{
    SomeRepository _someRepository;
    public SomeClass(SomeRepository someRepository)
    {
        _someRepository = someRepository;
    }

    public string ReadSomething() => _someRepository.ReadData();
}


var repositorySub = Substitute.For<SomeRepository>();
repositorySub.GetType().GetMethod("ActuallyPerformDataReading", BindingFlags.NonPublic | BindingFlags.Instance)
    .Invoke(repositorySub, new object[] {}).Returns("some test data");
var sut = new SomeClass(repositorySub);

var result = sut.ReadSomething(); //"some test data"

答案 1 :(得分:-1)

您不应该模拟受保护的类/方法。它被明确保护,所以你不能这样做。如果你需要嘲笑它,公开它。如果这是别人的方法并且您认为您需要嘲笑它,那么您可能测试不正确。

编辑:受保护方法中的任何功能只能由同一个类中的公共方法使用。嘲笑公共方法可以根据需要采取行动从受保护的方法获得一些期望的结果。