C# Generic method calling two different services - c#

I have the following method, which is to add product using the injected service! It is called inside a static calls hence it is static!
public static async Task AddNewProducts(Guid shopId)
{
var productAService = IoC.Services.GetService<IProductAService>();
var added = await productAService.AddProduct(shopId);
}
It works fine but I need to make it generic so that I can use different services with it.
Something like this!
public static async Task AddNewProducts<T>(Guid shopId)
where T : IProductAService, IProductBService
{
var productService = IoC.Services.GetService<T>();
var added = await productService.AddProduct(shopId);
}
However the second methods complains that the AddProduct method is ambiguous, not sure how I can make sure it is calling the right method from the related service!

Your 2 services need a common interface
public interface IProductService
{
void AddProduct(Guid shopId);
}
public interface IProductAService : IProductService
{
//specifics to service A
}
public interface IProductBService : IProductService
{
//specifics to service B
}
Then your static, generic method just constrains to the shared interface
public static async Task AddNewProducts<TProductService>(Guid shopId)
where TProductService : IProductService
{
var productService = IoC.Services.GetService<TProductService>();
await productService.AddProduct(shopId);
}
This gets slippery very quickly. You hinted that AddProduct is not a void, but returns a particular object. That's fine, you can make IProductService itself generic
public interface IProductService<TProduct>
{
TProduct AddProduct(Guid shopId);
}
public interface IProductAService : IProductService<ProductA>
{
//specifics to service A
}
public interface IProductBService : IProductService<ProductB>
{
//specifics to service B
}
But now you need to also pass the product type to the generic method, as I said - it gets slippery quickly (but maybe it'll do!)
public static async Task AddNewProducts<TProductService, TProduct>(Guid shopId)
where TProductService : IProductService<TProduct>
{
var productService = IoC.Services.GetService<TProductService<TProduct>>();
var added = await productService.AddProduct(shopId);
// Note "added" is of type TProduct
}
I call this situation "Generic hell". You are better of rethinking your design!

public static async Task AddNewProducts<T>(Guid shopId) where T : IProductAService, IProductBService
The problem with that line is that you're requiring T to implement both interfaces at once, not just one of them. You haven't even gotten to the errors that will spring up when you try to call this function, because presumably your class won't implement both.
Which leads me to question why you think you need to constrain your T like this. The only usage of T is to call Services.GetService<T>(), so the only constraint on it should be exactly the constraints that function requires, which are definitely not your two interfaces.

Related

Writing unit tests for classes that depend on external libraries/sdks

My code consists of the following components:
1 - IMyService: interface that defines properties/methods of the class that will implement it.
2 - MyService: concrete implementation of IMyService.
public interface IMyService
{
Task<MyResult> CreateAsync(string id, string json);
}
internal class MyService : IMyService
{
private readonly ExternalService _externalService;
public class MyService(ExternalService externalService)
{
this._externalService = externalService;
}
public async Task<MyResult> CreateAsync(string id, string json)
{
ServiceResult serviceResult = await this._externalService.RunAsync(id, json);
return new MyResult(serviceResult);
}
}
MyService class depends on third party library/SDK/package called ExternalService and implements method CreateAsync.
CreateAsync method takes 2 input parameters, invokes RunAsync method on ExternalService, receives result and creates my own class from result.
Question 1)
How would I approach unit testing CreateAsync method in MyService class? Is there any value in writing unit tests for it at all since it contains no logic?
Question 2)
ExternalService has its own Exceptions that it can throw when executing RunAsync method - should I capture exceptions thrown by RunAsync (wrapping try/catch around it) and cast them to my own Exception? For example - ExternalServiceException => MyServiceException.
Mock it with Moq and Autofixture. I don't know what unit testing framework you intend to use. So I would use Xunit as an example.
If it is calls to an external service you're only interested in testing what it can return.
First create an autofixture class. This is an attribute that is necessary for our test cases. More info here
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture()
.Customize(new AutoMoqCustomization()))
{
}
}
[Theory]
[AutoMoqData]
public async Task Validate_Service_ReturnResult([Frozen]Mock<IMyService> someService, ServiceResult mockResult, SomeClass sut){
//Set up interface to return what you want.
//In this case it returns mockResult always,
//but you can edit the properties of this to be whatever best fits your test case.
someService.Setup(x => x.CreateAsync(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(mockResult);
var result = await someService.Object.CreateAsync("ree", "skee");
//The class we are actually testing
var res =sut.DoSomething("someId", "someJson")
Assert.NotNull(res);
}
The [Frozen]-attribute makes sure that the behavior of the mocked someService is identical throughout all your code.
Doing all this is argueably a lot better than "faking" your interface for each testcase. Just imagine that you want CreateAsync to return different httpcodes like 404, 200, or 500. Have fun creating a new implementation of the interface for each case. With autofixture you just have set it up in the the beginning of your testcase.
The class we want to run our tests on
public class SomeClass{
IMyService someService;
public SomeClass(IMyservice someService){
this.someService = someService
}
public async Task<string> DoSomething(string id, string json){
var res = await this.someService.CreateAsync(id, json);
if(res.HttpStatusCode == 200){
//then do bla bla bla
...
}
}
Question 1: Yes. It is definitely worth it to unit test your services. You need to see if your code handles negative results. It would suck if this was a service that crashed because a result wasn't handled properly. For example if you expected an object from the service but receives null. Then before long you will have a null reference exception and a crashed service.
Question 2: Doesn't matter. Either way exceptions should be logged. If there is something important you want logged so you can query it easily eg. HttpCode. Then please do. It depends on two things. First: Can you handle the exceptions? And second: Do you log your exceptions to some central database?

c# generic interface where parameter is generic

I have an interface
public interface IOfflineBackedRepo<TSummary,TDetail>
{
Task SyncAsync();
}
this has different concrete implementations. I am trying to develop a service lets developers register different implementations of IOfflineBackedRepo interface and separately call SyncAsync at a later point in time. The new interface should be similar to the below, except this is not a valid syntax.
public interface ISyncManager<T> where T : IOfflineBackedRepo<TSummary, TDetail>
{
void Register(T repo);
Task SyncNowAsync(); // this loops through and calls SyncAsync on the repo
}
How to fix the syntax issue?
ISyncManager does not have anywhere mentioning TSummary,TDetail in it's scope
TSummary and TDetail is defined and exist only around IOfflineBackedRepo. When you try to use it anywhere else you must define a type you will use in substitute for them. It could be actual type or a type that you would get from generic argument but you must define it somewhere around ISyncManager
At the most basic ways,
public interface ISyncManager<T,U,V> where T : IOfflineBackedRepo<U,V>
{
void Register(T repo);
Task SyncNowAsync(); // this loops through and calls SyncAsync on the repo
}
For the ease of use I think you should just separate interface
public interface IOfflineBackedRepo
{
Task SyncAsync(); // this function is not typed specific right?
}
public interface IOfflineBackedRepo<TSummary,TDetail> : IOfflineBackedRepo
{
// other definition about type specific
}
public interface ISyncManager<T> where T : IOfflineBackedRepo
{
void Register(T repo);
Task SyncNowAsync(); // this loops through and calls SyncAsync on the repo
}
And I guess ISyncManager is actually just a collection. I think it would be better if you could just make extension method for collection
public static class SyncManagerExt
{
// Register is just Add to collection
public static Task SyncNowAsync(this ICollection<T> items) where T : IOfflineBackedRepo
{
// loops through items and calls SyncAsync on the repo
}
}

castle windsor interceptor on method that is calling by another method

Interceptor
public class CachingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// code comes here....
}
}
Business Layer
public class Business : IBusiness
{
public void Add(string a)
{
var t= GetAll();
// code comes here....
}
[CacheAttribute]
public string GetAll()
{
// code comes here....
}
}
Class
public class JustForTest
{
public JustForTest(IBusiness business)
{
//if GetAll is invoked directly caching works fine.
business.GetAll();
//if GetAll is invoked over Add method caching doesn't work.
business.Add();
}
}
add method calls GetAll method. If I invoke GetAll method directly, caching works. If Add method calls GetAll Method, caching doesn't work.
Thank You for helping.
Interface proxies are created by wrapping proxy target object so with interfaces this is not possible.
You can intercept calls on the same objects, but only for class proxy (provided the method is virtual).
See answer to a similar question.
You could also try to structure your code differently, move logic that needs to be cached to services that can be cached without using it's own functions.
The problem here is that the line
var t= GetAll();
is inside the class Business. It can be more clearly written as
var t = this.GetAll();
this is not an intercepted/wrapped instance.
Try dividing the responsibilities of the Business class as suggested here and here

Calling functions on intercepted method invocations in Simple Injector

What I am trying to achieve is to intercept the injection of a class, and call a specific method on the class to alter it's behaviour.
I have implemented the interceptor class that is given on the SimpleInjector website, and this is working, so I am able to get some functionality running when the class is intercepted.
My container is registering it as such:
container.InterceptWith<MyInterceptor>(type => type == typeof(IMyClass));
The class I am intercepting on looks as such:
public class MyClass : IMyClass
{
private IAnotherClass m_class;
public MyClass(IAnotherClass _class)
{
m_class = _class;
}
public void MethodToCall()
{
//changes properties on class
}
}
My interceptor class looks as such:
public class MyInterceptor : IInterceptor
{
private readonly ILogger logger;
public MyInterceptor(ILogger logger)
{
this.logger = logger;
}
public void Intercept(IInvocation invocation)
{
var watch = Stopwatch.StartNew();
// Calls the decorated instance.
invocation.Proceed();
var decoratedType = invocation.InvocationTarget.GetType();
logger.Trace(string.Format("{0} executed in {1} ms.",
decoratedType.Name, watch.ElapsedTicks));
}
}
What I am trying to achieve is to call a method on the intercepted IMyClass. So in the interceptor, call MyClass.MethodToCall()
I have tried to do something like this in the Intercept() method:
var classIntercepted = invocation.ReturnValue;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("MethodToCall");
object magicValue = method.Invoke(classIntercepted, null);
But, the invocation.ReturnValue is not returning the MyClass instance, but rather the IAnotherClass instance
Why don't you use a decorator instead of using interception? This is often much easier, more maintainable and faster.
Here's an example:
public class PropSetMyClassDecorator : IMyClass
{
private MyClass decoratee;
public PropSetMyClassDecorator(MyClass decoratee) {
this.decoratee = decoratee;
}
public void MethodToCall() {
this.decoratee.SetConnectionString();
this.decoratee.MethodToCall();
}
}
You can register this decorator as follows:
container.Register<IMyClass, PropSetMyClassDecorator>();
Do note that instead of registering MyClass, we only register the decorator. Since the decorator directly depends on MyClass (not on the interface) MyClass will be automatically resolved by Simple Injector.
Yet another option is to register an initializer as follows:
container.RegisterInitializer<MyClass>(instance => {
instance.SetConnectionString();
});
The initializer delegate will be called every time after a MyClass instance is constructed. The behavior is a bit different in this case, since the method isn't called every time, but only during construction. Usually however, this should be sufficient, since you should normally not change a service during runtime, since you are complicating things.
Ok, found a solution fairly shortly after posting the question.
I changed my Intercept function to be the following:
public void Intercept(IInvocation invocation)
{
// Calls the decorated instance.
invocation.Proceed();
var classIntercepted = invocation.InvocationTarget;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("SetConnectionString");
method.Invoke(classIntercepted, null);
}

How to stub a static method?

I am working on a brownfield application and am currently refactoring part of it. I am trying to do this in a TDD fashion but am running into a problem. Part of the code I am testing does
var siteLanguages = from sl in SiteSettings.GetEnabledSiteLanguages() select sl.LanguageID;
where GetEnabledLanguages has the following signature
public static List<LanguageBranch> GetEnabledSiteLanguages();
it in turns calls data access code to retrieve the relevant information. Up untill now I have used a interface and DI to use a different stub implementation for these kind of dependencies during unit testing. But since the GetEnabledSiteLanguages method is static this will not work. What is the "correct" way to do it in this case?
you could create a object which implements an interface and inject an implementation of this into the class which uses the SiteSettings class. The interface declare the method with the same signature as the static method(s) you need to intercept. Then you could mock out the interface for tests and create a single implementation which delegates to the static method for the actual code:
public interface ISiteSettings
{
public List<LanguageBranch> GetEnabledSiteLanguages()
}
public class ActualSiteSettings : ISiteSettings
{
public List<LanguageBranch> GetEnabledSiteLanguages()
{
return SiteSettings.GetEnabledSiteLanguages();
}
}
... in the dependent class:
public class DependentClass
{
private ISiteSettings m_siteSettings;
public DependentClass(ISiteSettings siteSettings)
{
m_siteSettings=siteSettings;
}
public void SomeMethod
{
var siteLanguages = from sl in m_siteSettings.GetEnabledSiteLanguages() select sl.LanguageID;
}
}
What about making your method such as:
public static Func<List<LanguageBranch>> GetEnabledSiteLanguages = () => {
//your code here
};
Now it becomes first class object (as Func delegate) and a stub can replace it
Look at Moles framework.
You can use tools like JustMock, TypeMock or moles. These tools allow you to mock everythings like static methods.

Categories

Resources