nSubstitute嘲笑例外

问题描述 投票:1回答:1

这是我的BLL服务,它与县合作:

public class CountryBLLService : ICountryBLL
{
    private readonly ITimeSheetContext _context;

    public CountryBLLService(ITimeSheetContext context)
    {
        _context = context;
    }
    public void CreateCountry(Country country)
    {
        _context.Countries.Create(country);
    }

    public Country GetCountry(Guid id)
    {
        return _context.Countries.Read(id);
    }

    public bool RemoveCountry(Guid id)
    {
        return _context.Countries.Delet(id);
    }

    public void UpdateCountry(Country country)
    {
        _context.Countries.Update(country);
    }
} 

这是一个TimeSheetContext:

 public class TimeSeetContext : ITimeSheetContext
{
    public ICountryRepository Countries { get; private set; }


    public TimeSeetContext()
    {
        Countries = new CountryRepository();
    }
}

所以,我想使用模拟TimeSheetContext来UnitTest throwException CountryBLL服务。但是我得到错误:像.Received()这样的NSubstitute扩展方法只能在使用Substitute.For()和相关方法创建的对象上调用。

这是我悲伤的尝试:

[TestClass]
public class CountryTestBLL
{
    ICountryBLL countrybLL;
    ITimeSheetContext context;

    [TestInitialize]
    public void Initialize()
    {
        context = Substitute.For<ITimeSheetContext>();
        countrybLL = new CountryBLLService(context);
    }

    [TestMethod]
    [ExpectedException(typeof(Exception),"Country Alreday exist")]
    public void CreateContry_throwEx()
    {
        countrybLL
            .When(x => x.CreateCountry(new Country()))
            .Do(x => { throw new Exception(); });

        countrybLL.CreateCountry(new Country());


    }
}
.net unit-testing mocking
1个回答
1
投票

欢迎来到StackOverflow! NSubstitute仅适用于您使用Substitute.For<T>创建的实例。所以你可以使用When..DoReturnsReceived等与context(使用NSubstitute创建),但不能使用countrybLL(使用new CountryBLLService创建)。

尝试通过context嘲笑:

[TestMethod]
[ExpectedException(typeof(Exception),"Country Alreday exist")]
public void CreateContry_throwEx()
{
    var existingCountry = new Country();
    context.Countries
           .When(x => x.CreateCountry(existingCountry))
           .Do(x => { throw new Exception(); });
    // Or context.Contries.CreateCountry(...).Returns(...) for non-void member 

    countrybLL.CreateCountry(existingCountry);
}

顺便说一句,当我在我的测试中遇到这样的问题时,我发现有时不使用模拟框架,而是手动创建我的类正在使用的依赖项的替代。这就是NSubstitute和其他模拟库自动为我们做的事情,但它可以帮助突出我正在测试的内容以及我为我的测试做什么。

例如:

class CountryExistsRepository : ICountryRepository {
    public void CreateCountry(Country c) {
        throw new Exception("country already exists");
    }
    // ... other members omitted ...
}

[TestMethod]
[ExpectedException(typeof(Exception),"Country already exist")]
public void CreateContry_throwEx()
{
    var existingCountry = new Country();

    var countrybLL = new CountryBLLService(
        new TimeSeetContext(new CountryExistsRepository()));

    countrybLL.CreateCountry(existingCountry);
}

我发现这使我更清楚我正在使用的真实代码,与我为测试所伪装的相比。然后,一旦我厌倦了手动实现这些案例,我就切换到一个模拟库来为我做。在这种情况下,它表明我们可能不需要替换TimeSeetContext,仅用于底层的ICountryRepository

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.