N заменить исключение имитатора

Вот моя служба 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();
    }
}

Итак, я хочу использовать службу UnitTest throwException CountryBLL, используя mock TimeSheetContext. Но я получаю ошибку: методы расширения NSubstitute, такие как .Received (), могут быть вызваны только для объектов, созданных с помощью 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());


    }
}
1
0
942
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добро пожаловать в StackOverflow! NSubstitute будет работать только с экземплярами, созданными с помощью Substitute.For<T>. Таким образом, вы можете использовать When..Do, Returns, Received и т. д. С 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.

Надеюсь это поможет.

Спасибо. Поскольку моя функция Create недействительна, мне пришлось использовать эту реализацию: context.Countries .When (x => x.Create (Arg.Any <Country> ())) .Do (x => {throw new CountryException (); });

Bojan Delić 14.09.2018 11:27

@ BojanDelić Я обновил пример, чтобы использовать When..Do, чтобы лучше отразить это. :)

David Tchepak 14.09.2018 11:32

Другие вопросы по теме