Dependency Injection using NSubstitute - c#

I have got a service class that has a constructor injection that takes IAppConfig. IAppConfig has couple of properties with just getters. And I would like to create an instance of this service class in my test project.
My Service class
IAppConfig _appConfig;
public class PeopleService(IAppConfig appConfig)
{
_appConfig = appConfig;
}
AppConfig Interface
public interface IAppConfig
{
string BaseURL {get;}
string AnotherProperty {get;}
}
How do I use NSubstitute to mock the IAppConfig to create an instance of PeopleService.
I have tried the below code, but the properties that I set are empty string.
var _appConfig = Substitute.For<IAppConfig>();
_appConfig.BaseURL.Returns("http://localhost");
new PeopleService(_appConfig);
But the property set in the _appConfig is not working. I appreciate if someone can help me.

Showing this since this is too much to put in a comment.
This simplified example shows that the framework works as expected and that you need to clarify your actual issue better.
[TestClass]
public class MyTestClass {
[TestMethod]
public void NSubstitute_Mocking_ReadOnly_Properties_Works() {
//Arrange
var expected = "http://localhost";
var _appConfig = Substitute.For<IAppConfig>();
_appConfig.BaseURL.Returns(expected);
var subject = new PeopleService(_appConfig);
//Act
var actual = subject.URL;
//Assert
actual.Should().Be(expected);
}
}
class PeopleService {
IAppConfig _appConfig;
public PeopleService(IAppConfig appConfig) {
_appConfig = appConfig;
}
public string URL => _appConfig.BaseURL;
}
public interface IAppConfig {
string BaseURL { get; }
string AnotherProperty { get; }
}
The above example passed when tested.

Related

ServiceStack IAppSettings was not ready and would result NULL reference exception if used in constructor

It seems like the IAppSettings implementation was not ready from IoC in the constructor.
Before I go into details, I've read similar problems:
ServiceStack doesn't auto-wire and register AppSettings
Instantiation of POCO objects with ServiceStack's IAppSettings is not working
Both were answered by #mythz that he was not able to reproduce it.
From the Doc
"ServiceStack made AppSettings a first-class property, which defaults to looking at .NET's App/Web.config's.": https://docs.servicestack.net/appsettings#first-class-appsettings
And there is default IoC registration already in Funq to give you AppSettings when you ask for IAppSettings:
What I have
All my codes are in the repo: https://github.com/davidliang2008/MvcWithServiceStack
The demo app is just an ASP.NET MVC app (.NET 4.8) that built using the template, the simplest you can get, with ServiceStack (5.12.0) installed:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
...
new AppHost().Init();
}
}
public class AppHost : AppHostBase
{
public AppHost() : base("MvcWithServiceStack", typeof(ServiceBase).Assembly) { }
public override void Configure(Container container)
{
SetConfig(new HostConfig
{
HandlerFactoryPath = "api";
}
ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
}
}
Then I have a base class for the ServiceStack Service, and a HelloService just to demo:
public abstract class ServiceBase : Service { }
public class HelloService : ServiceBase
{
public IAppSettings AppSettings { get; set; }
public object Get(HelloRequest request)
{
return new HelloResponse
{
Result = $"Hello, { request.Name }! Your custom value is { AppSettings.Get<string>("custom") }."
};
}
}
[Route("/hello/{name}")]
public class HelloRequest : IReturn<HelloResponse>
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
What works
When you're not using IAppSettings in the constructor, whether in the HelloService or its base class ServiceBase, everything works out fine.
When you clone the project to your local, if you navigate to /api/hello/{your-name}, you will see its response would be able to get the custom value from web.config:
What doesn't work
When you're trying to get the IAppSettings and initialize something else with some app setting values in the constructor - whether it's in the child class or the base class, IAppSettings will fail to get the implementation from IoC, and result a NULL reference exception:
public abstract class ServiceBase : Service
{
public IAppSettings AppSettings { get; set; }
public ServiceBase()
{
// AppSettings would be NULL
var test = AppSettings.Get<string>("custom");
}
}
OR
public class HelloService : ServiceBase
{
public HelloService()
{
// AppSettings would be NULL
var test = AppSettings.Get<string>("custom");
}
}
You cannot use any property dependency in the constructor since the properties can only be injected after the class is created and the constructor is run.
You'll only be able to access it in the Constructor by using constructor injection, e.g:
public class HelloService : ServiceBase
{
public HelloService(IAppSettings appSettings)
{
var test = appSettings.Get<string>("custom");
}
}
Or accessing the dependency via the singleton:
public class HelloService : ServiceBase
{
public HelloService()
{
var test = HostContext.AppSettings.Get<string>("custom");
}
}

What is the better way to handle HTTP connections in a custom class model on Net Core?

I have a class model using GRASP pattern design, specifically Controller pattern, so ProductController handles all the Product instances, and this handle all the Kardex instances.
ProductController can save, edit and delete products.
Product can save and delete kardex movements.
Only using OOP I can handle this, but I need that some methods calls an API to save and/or get data from a DB.
My app will be constantly doing operations with this API, so I decide to use IHttpClientFactory with DI.
If i inject controllers with their respectives interfaces is not a problem, but if a Product instance have to SaveKardex, i will have to inject it to use HttpClientFactory, preventing instantiate. So i did this:
public class Product
{
private readonly IHttpClientFactory _httpClientFactory;
public int prop1 { get; set; }
public Product(IHttpClientFactory httpClientFactory) //this works
{
_httpClientFactory = httpClientFactory;
}
public Product() //this also works
{
prop1 = 10;
}
public async Task<bool> SaveKardex(Kardex kardex)
{
var client = _httpClientFactory.CreateClient("BdClient");
var uriString = client.BaseAddress + $"product/kardex";
var message = RequestBuilder.RequestMessage(HttpMethod.Post, uriString);
var res = await client.SendAsync(message);
....
....
return true;
}
}
If I instanciate a new Product or is deserialized, i could not call SaveKardex method because i will not use the injected instance and httpClientFactory would be null.
What can i do? Any suggestions?
I thought using HttpClient instances, but is this the best way considering a lot of connections to the API?
Thanks!
I solved this redesigning my model as follow: (This was suffering from tight coupling and low cohesion as #Nkosi said).
An EntityLayer was created with all properties that would be send to BD and vice versa.
An Interface was created where operations with BD are declared.
A "Service class" was created wich implement the interface. This class is inyected on .net core and not other one.
Finally, all instances of Product receives this Interface (wich is implemented by ProductService), so this way i can call "bd operations".
public class EntityProduct
{
public int prop1 {get; set; }
}
public interface IProductOperations
{
Task<bool> SaveKardex(int prop);
}
public class ProductService : IProductOperations //only this class is inyected
{
private IHttpClientFactory httpClientFactory;
public ProductService(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public async Task<bool> SaveKardex(int prop)
{
var client = _httpClientFactory.CreateClient("BdClient");
var uriString = client.BaseAddress + $"product/kardex/{prop}";
var message = RequestBuilder.RequestMessage(HttpMethod.Post, uriString);
var res = await client.SendAsync(message);
....
....
return true;
}
}
public class Product
{
private IProductOperations _productOperations;
public EntityProduct Entity { get; set; }
public Product(IProductOperations productOperations)
{
_productOperations = productOperations;
}
public async Task<bool> SaveKardex(int prop)
{
var result = await _productOperations.SaveKardex(prop);
....
....
return true;
}
}
I could do this thanks to this answer by #robert-paulen

Mocking property depending on HttpRequest [duplicate]

This question already has an answer here:
Mock HttpRequest in ASP.NET Core Controller
(1 answer)
Closed 4 years ago.
I'm having the following setup:
public class ExampleBaseController : Microsoft.AspNetCore.Mvc.Controller
{
public UserDetails UserDetails => Request.GetUserDetailsFromHttpHeaders();
}
public class ExampleConcreteController : ExampleBaseController
{
// UserDetails is being used in here
// this is the class under test
I need to be able to inject UserDetails during production run and also be able to mock it during tests.
Since UserDetails depends on Request and Request is a member of Microsoft.AspNetCore.Mvc.Controller I do not know how to achieve this.
If you want to mock something, you should first allow mocking on it. If you want to mock UserDetails you should allow mocking on its getter and pass required context inside newly crafted contract:
public class ExampleBaseController : Microsoft.AspNetCore.Mvc.Controller
{
private readonly IUserDetailsProvider _userDetailsProvider;
public UserDetails UserDetails => _userDetailsProvider.Get(Request);
public ExampleBaseController(IUserDetailsProvider userDetailsProvider)
{
_userDetailsProvider = userDetailsProvider;
}
}
So, in test you mock IUserDetailsProvider to return some "foobar". In production you just invoking GetUserDetailsFromHttpHeaders() method on passed inside Request.
To answer question about Request and Controller relations. Controller depends on Request, yes, and Microsoft thought that it will be good to strongly merge them together instead of passing dependency, for example like this:
public class FooBarController : Microsoft.AspNetCore.Mvc.Controller
{
private readonly System.Web.HttpRequestBase _request;
public FooBarController(System.Web.HttpRequestBase request)
{
_request = request;
}
}
Or even like this:
public class FooBarController : Microsoft.AspNetCore.Mvc.Controller
{
public void ProcessRequest(System.Web.HttpRequestBase request)
{
//request here
}
}
They instead used Property injection, which leaves developer with no way to affect injection. This is a problem. But not unsolvable - you just pass context inside (by delegate, by interface, by reference), if you need one of those coupled together objects.
It could be not so convinient as solution, proposed by #eocron, but still:
public interface IWithUserDetails
{
UserDetails UserDetails();
}
public class ExampleBaseController : Microsoft.AspNetCore.Mvc.Controller, IWithUserDetails
{
public UserDetails UserDetails()
{
return Request.GetUserDetailsFromHttpHeaders();
}
}
Same name for class and method is not a best way to do, but it was like it in the example with a property
Here is another point of view:
public interface IUserDetailsProviderOptions
{
Func<UserDetails> UserDetailsProvider { get; set; }
}
public class DefaultUserDetailsProviderOptions : IUserDetailsProviderOptions
{
public Func<UserDetails> UserDetailsProvider {get; set;}
}
public class ExampleBaseController : Microsoft.AspNetCore.Mvc.Controller
{
private readonly Func<UserDetails> _userDetailsProvider;
public UserDetails UserDetails => _userDetailsProvider();
public ExampleBaseController(IUserDetailsProviderOptions options)
{
_userDetailsProvider = options.UserDetailsProvider ??
Request.GetUserDetailsFromHttpHeaders;
}
}
Register in Startup.cs like this:
services.AddSingleton<IUserDetailsProviderOptions, DefaultUserDetailsProviderOptions>();
In testing you could do:
public class StubUserDetailsOption : IUserDetailsProviderOptions
{
public Func<UserDetails> UserDetailsProvider { get; set; } = () => new StubDetails();
}
var controller = new ExampleBaseController(new StubUserDetailsOption());
and do testing.

Create class and auto-initialize dependencies with FakeItEasy

Is it possible to create a class under test with FakeItEasy, where all dependencies that are declared in the constructor are initialized automatically with fakes?
Imagine the class:
public class Inserting
{
public Inserting(
ITransactionService transactionService,
ISharedData sharedData)
{
TransactionService = transactionService;
SharedData = sharedData;
}
public ITransactionService TransactionService { get; }
public ISharedData SharedData { get; }
public void Enter()
{
TransactionService.StartTransaction();
}
}
Then I am creating all fake-objects in the test setup and construct my class under test with those fakes:
public class InsertingTest
{
private Inserting _inserting;
private ISharedData _fakeSharedData;
private ITransactionService _fakeTransactionService;
[SetUp]
public void SetUp()
{
_fakeTransactionService = A.Fake<ITransactionService>();
_fakeSharedData = A.Fake<ISharedData>();
_inserting = new Inserting(_fakeTransactionService, _fakeSharedData);
}
[Test]
public void TestEnter()
{
// Arrange
// Act
_inserting.Enter();
// Assert
A.CallTo(() => _fakeTransactionService.StartTransaction().MustHaveHappened();
}
}
But I saw in the Java-world, that when using Mockito and Dagger 2, you can do something like this:
public class PhoneDialer {
private Activity activity;
private PhoneCallListener phoneCallListener;
#Inject
public PhoneDialer(Activity activity, PhoneCallListener phoneCallListener) {
this.activity = activity;
this.phoneCallListener = phoneCallListener;
}
}
public class PhoneDialerTest {
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Mock
PhoneCallListener phoneCallListener;
#Mock
Activity activity;
#InjectMocks
PhoneDialer dialer;
#Test
public void test_dialer() throws Exception {
// Arrange
// Act
dialer.callNumber("abc");
// Assert
Mockito.verify(phoneCallListener, times(1)).startCall();
}
}
and the mocked classes are initialized automatically with fakes. Is there an equivalent procedure or function in C# with FakeItEasy?
I think you want something like
Automatically inject fakes in test fixture with FakeItEasy. You use [Fake] to mark fakes to inject and [UnderTest] to mark the production type to test.
We really should put this into the documentation.
Alternatively,
AutoFixture has an AutoFixture.AutoFakeItEasy module,
there's Autofac FakeItEasy integration, and also
Ninject FakeItEasy integration
I saw 'Automatically inject fakes in text fixture with FakeItEasy' and my initial reaction was surprise that it differed from my preconception, mainly because it needs 'intrusive' changes that attribute the test code... but perhaps that is an overreaction.
The FakeAttribute and UnderTestAttribute do force what is potentially a good structural constraint on your test (and system) design...
[FWLIW, before googling this, I had imagined the following:
containerBuilder.RegisterAsFakeCallingBaseType<SystemUnderTest>();
You can do something like this with Autofac's registration sources.
using Autofac;
using Autofac.Core;
using Autofac.Core.Activators.Delegate;
using Autofac.Core.Lifetime;
using Autofac.Core.Registration;
using FakeItEasy;
using Xunit;
public interface IDependOnSomething { }
public class IImplementThat : IDependOnSomething { }
public class CanIResolveIt
{
public CanIResolveIt(IDependOnSomething it)
{
}
}
public class FakeRegistrationSourceTest
{
[Fact]
public void BasicTest()
{
var container = new ContainerBuilder();
container.RegisterTypes<IImplementThat>().As<IDependOnSomething>();
container.RegisterSource(new FakeRegistrationSource<CanIResolveIt>());
var c = container.Build();
var theFake = c.Resolve<CanIResolveIt>();
Assert.NotNull(theFake);
}
}
public class FakeRegistrationSource<T> : IRegistrationSource
where T : class
{
public bool IsAdapterForIndividualComponents => false;
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if (swt == null || !typeof(T).IsAssignableFrom(swt.ServiceType)) // TODO: is this the right way around?
{
return Enumerable.Empty<IComponentRegistration>();
}
var registration = new ComponentRegistration(
Guid.NewGuid(),
new DelegateActivator(swt.ServiceType, (context, #params) =>
{
List<object> v = new List<object>();
foreach (ParameterInfo p in typeof(T).GetConstructors().Single().GetParameters())
{
v.Add(context.Resolve(p.ParameterType));
}
return A.Fake<T>(that => that.CallsBaseMethods().WithArgumentsForConstructor(v));
}),
new CurrentScopeLifetime(),
InstanceSharing.None,
InstanceOwnership.OwnedByLifetimeScope,
new[] { service },
new Dictionary<string, object>());
return new IComponentRegistration[] { registration };
}
}
Main advantage of this approach is that it knows how to instantiate fake objects subclassing classes with constructor parameters, and inheriting their default behavior, when they have a single constructor (choosing intelligently from multiple constructors would be an obvious challenge that I'm not going to tackle...)
An obvious drawback is explicit registration every time you want something faked. AutoFake and so on offer ways to overcome that with faking of just about everything by default, which might well be what you want... and you can override it if not.]

Registration confusion with autofac and console app

I'm trying to use autofac for dependency injection in my console app. I'm running into issues where autofac can't find constructors for certain interfaces/classes.
Here is my latest example:
IRepository:
public interface IRepository<Planetary>
{
IEnumerable<Planetary> Get();
}
IPlanetaryRepository:
public interface IPlanetaryRepository : IRepository<Planetary>
{
IQueryable<Planetary> GetPlanetary(SystemProbe user);
}
PlanetaryService:
public interface IPlanetaryService
{
Task<Planetary> Clone(Planetary source);
}
public sealed class PlanetaryService : IPlanetaryService
{
private IPlanetaryRepository Repo { get; }
public PlanetaryService(IPlanetaryRepository repo)
{
Repo = repo;
}
}
Scheduler:
public class Scheduler
{
private static IContainer Container { get; set; }
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<PlanetaryService>().As<PlanetaryService>();
builder.RegisterType<IPlanetaryRepository>().As<IPlanetaryRepository>();
Container = builder.Build();
GenerateSchedules();
}
public static void GenerateSchedules()
{
using (var scope = Container.BeginLifetimeScope())
{
var repo = scope.Resolve<PlanetaryService>(); <-- line where exception is thrown
}
}
}
No constructors on type 'IPlanetaryRepository' can be found with the
constructor finder
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'.
If I take out IPlanetaryRepository, I get this exception:
Cannot resolve parameter IPlanetaryRepository repo of constructor...
So I'm not really sure what to do. 'PlanetaryService' needs 'IPlanetaryRepository' as a parameter, but IPlanetaryRepository doesn't have a constructor.
Is there a way to rectify this?
You don'y have any classes that implement IPlanetaryRepository so it can't find the constructor.

Categories