Как имитировать классы с помощью фабричных методов в Substitute? (для использования ForPartsOf для сохранения поведения C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Как имитировать классы с помощью фабричных методов в Substitute? (для использования ForPartsOf для сохранения поведения

Сообщение Anonymous »


I want to mock a Logger using NSubstitute. But instead of using Substitute.For, I want to use Substitute.ForPartsOf to:
  • both call the real implementation (to continue logging to the console)
  • and check the result using .Received, i.e. check whether something was logged.

The issue is, my Logger does have a factory method (Create), which returns a new instance of the logger.

Now, can I use this with NSubstitute to substitute it?

Here a full MWE.

I tried:
  • For and ForPartsOf, which always fail due to the private constructor
  • I switched to CallBase, but this also does not work, because I need to have a concrete instance
  • in the last try, ForCasting_UsingCallBase, I even tried casting the successfully created For substitute to the concrete type, to have a concrete type for the base method, which it complained, was missing; but in this case the casting fails

public interface ILogSettings { } public interface ISomeLogger { public void LogSomething(string anything); } public class SomeLogger : ISomeLogger { private SomeLogger() => throw new NotSupportedException("let's assume this constructor is not good to call"); private SomeLogger(ILogSettings logSettings) => CreateLogger(logSettings); private static void CreateLogger(ILogSettings logSettings) { Console.WriteLine(); Console.WriteLine("Logger created."); // does something with logSettings, irrelevant here } /// /// Factory method here for creating logger! /// [PublicAPI] public static SomeLogger Create(ILogSettings? logSettings) => logSettings != null ? new SomeLogger(logSettings) : throw new ArgumentNullException(nameof(logSettings)); public void LogSomething(string anything) => Console.WriteLine(anything); } [TestFixture] public class SubstituteReproducerTest { [Test] public void For_WorksButShowsNoLogging() { var logger = Substitute.For(); // This here is mocked, so it cannot/does not actually call the "real" method. // Thus, no logging is shown in the test. logger.LogSomething("sth"); // I can, however, check the received call, of course. logger.ReceivedWithAnyArgs(1).LogSomething(default!); } [Test] public void ForPartsOf_OnInterface() { var logger = Substitute.ForPartsOf(); // This DOES NOT work! // Can only substitute for parts of classes, not interfaces or delegates. Try `Substitute.For instead. } [Test] public void ForPartsOf_WithPrivateConstructor() { var logger = Substitute.ForPartsOf(); // This DOES NOT work! // Could not find a parameterless constructor. (Parameter 'constructorArguments') } [Test] public void For_WithPrivateConstructor() { var logger = Substitute.For(); // This DOES NOT work! // Could not find a parameterless constructor. (Parameter 'constructorArguments') } [Test] public void For_WithFactoryMethod() { var settings = Substitute.For(); // This DOES NOT work! // The constructor args are supposed to be there. var logger = Substitute.For(() => SomeLogger.Create(settings)); // Could not find a parameterless constructor. (Parameter 'constructorArguments') } [Test] public void ForPartsOf_WithFactoryMethod() { var settings = Substitute.For(); // This DOES NOT work! // The constructor args are supposed to be there. var logger = Substitute.ForPartsOf(() => SomeLogger.Create(settings)); // Could not find a parameterless constructor. (Parameter 'constructorArguments') } [Test] public void For_UsingCallBase() { var logger = Substitute.For(); logger.WhenForAnyArgs(x => x.LogSomething(default!)).CallBase(); // This DOES NOT work! // NSubstitute.Exceptions.CouldNotConfigureCallBaseException : Cannot configure the base method call as base method implementation is missing. You can call base method only if you create a class substitute and the method is not abstract. } [Test] public void For_UsingCallBaseWithConcreteClass() { var logger = Substitute.For(); // This DOES NOT work! // Could not find a parameterless constructor. (Parameter 'constructorArguments') // And ForPartsOf would fail to, as given and tried in ForPartsOf_WithPrivateConstructor. } [Test] public void ForCasting_UsingCallBase() { var logger = Substitute.For(); var loggerConcrete = logger as SomeLogger; // --> results in 'null' loggerConcrete.WhenForAnyArgs(x => x.LogSomething(default!)).CallBase(); // This DOES NOT work! // NSubstitute.Exceptions.CouldNotConfigureCallBaseException : Cannot configure the base method call as base method implementation is missing. You can call base method only if you create a class substitute and the method is not abstract. } } I know I can make methods virtual to be substitut'able, but this does not work here, as the Logger/class is from a library I use.


Источник: https://stackoverflow.com/questions/781 ... partsof-to
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Полностью асинхронное решение для фабричных светильников в стиле FastAPI?
    Anonymous » » в форуме Python
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous
  • Как Koin управляет памятью для отдельных, фабричных и ограниченных объектов?
    Anonymous » » в форуме Android
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous
  • Как Koin управляет памятью для отдельных, фабричных и ограниченных объектов?
    Anonymous » » в форуме Android
    0 Ответы
    14 Просмотры
    Последнее сообщение Anonymous
  • Как Koin управляет памятью для отдельных, фабричных и ограниченных объектов?
    Anonymous » » в форуме Android
    0 Ответы
    7 Просмотры
    Последнее сообщение Anonymous
  • Как имитировать/имитировать события очереди Laravel в тестах?
    Anonymous » » в форуме Php
    0 Ответы
    31 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»