Mapper decorator not getting compiled - spring-mvc

Mapper decorator for my mapper is not getting compiled.Mapper is getting compiled, but not the decorator. Because, during the build I'm getting the type conversion error, even though I'm doing it in the mapper decorator. Is there anything more to add?
mapper code:
#Mapper
#DecoratedWith(OneMapperDecorator.class)
public interface OneMapper {
public TwoObject convertToTwoObject(OneObject one);
}
decorator code:
public abstract class OneMapperDecorator implements OneMapper {
private final OneMapper delegate;
public OneMapperDecorator (OneMapper delegate) {
this.delegate = delegate;
}
#Override
public TwoObject convertToTwoObject(OneObject one)
{
TwoObject two=delegate.convertToTwoObject(one);
two.setTotalFare(new BigDecimal(one.getPrice()));//string to bigdecimal conversion
return two;
}
}

The decorator is meant to augment the mapping not to replace it. MapStruct has no way of knowing that you are mapping your totalFare in the decorator. You have 2 options:
Define a custom mapping method
In your OneMapper you can add a default method that would perform the mapping (as the error says.
#Mapper
#DecoratedWith(OneMapperDecorator.class)
public interface OneMapper {
#Mapping(target = "totalFare", source = "price");
TwoObject convertToTwoObject(OneObject one);
default BigDecimal map(String value) {
return value == null ? null : new BigDecimal(value);
}
}
Ignore the mapping
In case you want to do the mapping in your decorator then you need to tell MapStruct to not map it.
#Mapper
#DecoratedWith(OneMapperDecorator.class)
public interface OneMapper {
#Mapping(target = "totalFare", ignore = true);
TwoObject convertToTwoObject(OneObject one);
}
One advise from me if you are using your delegate only to map extra fields I would either add custom methods or use #AfterMapping and #BeforeMapping to handle that.

Related

Xamarin Android binding does not implement interface issue

I've a java binding for android which somewhat works bar the new feature I'm trying to integrate with. Only now I have realised that the intended callback is not happening. Here are the classes (decompiled to java) in question:
At the top level we have
public interface MyPackage {
MyPackage.Companion Companion = MyPackage.Companion.$$INSTANCE;
public static final class Companion {
#Nullable
private static MyEventHandler myEventHandler;
// $FF: synthetic field
static final MyPackage.Companion $$INSTANCE;
#Nullable
public final MyEventHandler getMyEventHandler() {
return myEventHandler;
}
public final void setMyEventHandler(#Nullable MyEventHandler var1) {
myEventHandler = var1;
}
private Companion() {
}
static {
MyPackage.Companion var0 = new MyPackage.Companion();
$$INSTANCE = var0;
}
}
}
MyEventHandler class:
public abstract class MyEventHandler {
public abstract void handleEvent(#NotNull String var1, #NotNull Properties var2);
}
Properties class:
import java.util.Map;
public class Properties extends r {
public Properties() {
}
Properties(Map<String, Object> var1) {
super(var1);
}
public Properties a(String var1, Object var2) {
super.b(var1, var2);
return this;
}
}
and the problematic r class:
public class r implements Map<String, Object> {
private final Map<String, Object> a;
various implementations...
}
So I noticed the issue when I couldnt override the HandleEvent method at the integration level and started looking at the Binding logs and found:
Warning=>
BINDINGSGENERATOR: Warning BG8801: Invalid parameter type MyPackage...Properties in method HandleEvent in managed type MyPackage.MyEventHandler. (BG8801)
And in build logs:
message BG0000: warning BG8102: Class MyPackage....Properties has unknown base type MyPackage....r.
warning BG8801: Invalid parameter type MyPackage...Properties in method HandleEvent in managed type MyPackage.MyEventHandler.
As it was obvious r is an obfuscated class I need to make chagnes to my Metadata so I went ahead and popped in:
<attr path="/api/package[#name='MyPackage']/class[#name='r']" name="obfuscated">false</attr>
Which resulted in the R being generated but now I get the 5 following compile error:
Error CS0535: 'R' does not implement interface member 'IMap.EntrySet()' (CS0535)
Error CS0738: 'R' does not implement interface member 'IMap.KeySet()'. 'R.KeySet()' cannot implement 'IMap.KeySet()' because it does not have the matching return type of 'ICollection'. (CS0738)
Error CS0535: 'R' does not implement interface member 'IMap.Put(Object?, Object?)' (CS0535)
Error CS0535: 'R' does not implement interface member 'IMap.PutAll(IDictionary?)' (CS0535)
Error CS0738: 'R' does not implement interface member 'IMap.Values()'. 'R.Values()' cannot implement 'IMap.Values()' because it does not have the matching return type of 'ICollection'. (CS0738)
I tried to make a managed return using
<attr path="/api/package[#name='MyPackage']/class[#name='r']/method[#name='entrySet' and count(parameter)=0]" name="managedReturn">Java.Util.IMap</attr>
With same number of compile error as above. Then I tried removing the node using:
<remove-node path="/api/package[#name='MyPackage']/class[#name='r']/method[#name='entrySet']"/>
Still no luck. :(
What am I missing here? Any pointers/suggestions will be appreciated!
It seems like you are trying to expose a Map to C# and as you stated, Java Generics are not handled very well.
In a very popular social network you received an answer from #mattleibow. I do not take credit for his answer but I went to check nonetheless and it seems fine.
If you look at the description of the Java.Lang.HashMap type
https://learn.microsoft.com/en-us/dotnet/api/java.util.hashmap?view=xamarin-android-sdk-9 it's a good candidate for you to expose.
You can also try with the corresponding interface for better safety https://learn.microsoft.com/en-us/dotnet/api/java.util.imap?view=xamarin-android-sdk-9
If it works you will still have to cast the types yourself.
Please answer to the comment to say that problem is solved for the sake of future generations arriving on this post :D
Credit is not mine so don't give it to me :-)
John,
I got arround fixing it by providing implementation of the the said methods in a partial class. Basically added a new file called R.cs under Additions folder as follows:
namespace YourNameSpace
{
public partial class R
{
public void PutAll(System.Collections.IDictionary p0)
{
PutAll(p0);
}
public Java.Lang.Object Put(Java.Lang.Object key, Java.Lang.Object value)
{
return Put(key, value);
}
public System.Collections.ICollection EntrySet()
{
return EntrySet();
}
public System.Collections.ICollection KeySet()
{
return KeySet();
}
public System.Collections.ICollection Values()
{
return Values();
}
}
}
I couldn't get it to work by adding XML transformation, but I think there was some tooling issue.

How to make a field set-able only inside extension method

Hello i want to be able to set the a of a field of an object only in an extension method. I would want that this field to either be completelely private , or be just get-able from outside:
public class Myclass
{
private int Value{get;set;}
}
public static class Ext
{
public Myclass SetValue(this Myclass obj,int val)
{
this.obj.Value=val;
return obj;
}
}
As you can see in the above example , i have to declare Value public to be able to access it inside the extension , i would be ok with that if i could make the variable only get-ablefrom outside.
I need this functionality because i want to develop something like a fluent api , where you can only set some variables using the extension.
ex:
a=new Myclass();
a.SetValue1(1).SetValue2(2);//--some code //--a.SetValue3(3);
It sounds like you're using the wrong tool for the job, extension methods don't have access non-public members.
The behavior you want is restricted to instance methods or properties. My recommendation is to add an instance method to the class.
If that doesn't persuade you, then you can instead use reflection to update the private instance variable:
public static class Ext
{
public Myclass SetValue(this Myclass obj,int val)
{
var myType = typeof(Myclass);
var myField = myType.GetField("Value", BindingFlags.NonPublic | BindingFlags.Instance);
myField.SetValue(obj, val);
return obj;
}
}
Please note that this has the following gotchas:
There are no compile time checks to save you if you decide to rename the field Value. (though unit tests can protect you)
Reflection is typically much slower than regular instance methods. (though performance may not matter if this method isn't called frequently)
you want it to do it with extension method but you cannot in this case.
Your best option is
public class Myclass
{
public int Value{get; private set;}
public Myclass SetValue(int val)
{
this.Value=val;
return obj;
}
}

Resolve named registration dependency in Unity with runtime parameter

I have a following problem. I register my components and initialize them in Unity like this (example is for a Console application):
public class SharePointBootstrapper : UnityBootstrapper
{
...
public object Initialize(Type type, object parameter) =>
Container.Resolve(type,
new DependencyOverride<IClientContext>(Container.Resolve<IClientContext>(parameter.ToString())),
new DependencyOverride<ITenantRepository>(Container.Resolve<ITenantRepository>(parameter.ToString())));
public void RegisterComponents()
{
Container
.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString())
.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString())
.RegisterType<ITenantRepository, DocumentDbTenantRepository>(SharePointClientContext.Online.ToString())
.RegisterType<ITenantRepository, JsonTenantRepository>(SharePointClientContext.OnPremise.ToString());
}
}
public enum SharePointClientContext
{
Online,
OnPremise
}
class Program
{
static void Main(string[] args)
{
...
bootstrap.RegisterComponents();
var bla = bootstrap.Initialize(typeof(ISharePointManager), SharePointClientContext.Online);
}
}
So, I register my components in MVC, WCF, Console etc. once with RegisterComponents() and initialize them with Initialize().
My question is, if I want to initialize specific named registration at runtime, from e.g. user input, can it be done otherwise as the code presented (with InjectionFactory or similar)?
This code works fine, but I'm not happy with its implementation. I have a feeling that it could be written in RegisterComponents() instead of Initialize() so that it accepts a parameter of some type, but I don't know how to do it.
Or, is maybe my whole concept wrong? If so, what would you suggest? I need to resolve named registration from a parameter that is only known at runtime, regardless of the technology (MVC, WCF, Console, ...).
Thanks!
Instead of doing different registrations, I would do different resolves.
Let's say that you need to inject IClientContext, but you want different implementations depending on a runtime parameter.
I wrote a similiar answer here. Instead of injecting IClientContext, you could inject IClientContextFactory, which would be responsible for returning the correct IClientContext. It's called Strategy Pattern.
public interface IClientContextFactory
{
string Context { get; } // Add context to the interface.
}
public class SharePointOnlineClientContext : IClientContextFactory
{
public string Context
{
get
{
return SharePointClientContext.Online.ToString();
}
}
}
// Factory for resolving IClientContext.
public class ClientContextFactory : IClientContextFactory
{
public IEnumerable<IClientContext> _clientContexts;
public Factory(IClientContext[] clientContexts)
{
_clientContexts = clientContexts;
}
public IClientContext GetClientContext(string parameter)
{
IClientContext clientContext = _clientContexts.FirstOrDefault(x => x.Context == parameter);
return clientContext;
}
}
Register them all, just as you did. But instead of injecting IClientContext you inject IClientContextFactor.
There also another solution where you use a Func-factory. Look at option 3, in this answer. One may argue that this is a wrapper for the service locator-pattern, but I'll leave that discussion for another time.
public class ClientContextFactory : IClientContextFactory
{
private readonly Func<string, IClientContext> _createFunc;
public Factory(Func<string, IClientContext> createFunc)
{
_createFunc = createFunc;
}
public IClientContext CreateClientContext(string writesTo)
{
return _createFunc(writesTo);
}
}
And use named registrations:
container.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString());
container.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString());
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(), // Or any other lifetimemanager.
new InjectionConstructor(
new Func<string, IClientContext>(
context => container.Resolve<IClientContext>(context));
Usage:
public class MyService
{
public MyService(IClientContextFactory clientContextFactory)
{
_clientContextFactory = clientContextFactory;
}
public void DoStuff();
{
var myContext = SharePointClientContext.Online.ToString();
IClientContextclientContext = _clientContextFactory.CreateClientContext(myContext);
}
}

How can I make AutoMoqCustomization use Strict MockBehavior?

Using AutoFixture with the AutoFixture.AutoMoq package, I sometimes find tests that weren't configured to correctly test the thing they meant to test, but the problem was never discovered because of the default (Loose) Mock behavior:
public interface IService
{
bool IsSomethingTrue(int id);
}
void Main()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var service = fixture.Freeze<Mock<IService>>();
Console.WriteLine(service.Object.IsSomethingTrue(1)); // false
}
I'd like to make Mocks get created with Strict behavior, so we're forced to call Setup() for the methods we expect to be called. I can do this for each individual mock like this:
fixture.Customize<Mock<IService>>(c => c.FromFactory(() => new Mock<IService>(MockBehavior.Strict)));
But after combing through source code for AutoMoqCustomization() and the various ISpecimenBuilder and other implementations, I'm pretty lost as to the best way to just make all Mocks get initialized with strict behavior. The framework appears to be very flexible and extensible, so I'm sure there's a simple way to do this--I just can't figure out how.
There's no simple built-in feature that will enable you to do something like that, but it shouldn't be that hard to do.
Essentially, you'd need to change MockConstructorQuery so that it invokes the constructor that takes a MockBehavior value, and pass in MockBehavior.Strict.
Now, you can't change that behaviour in MockConstructorQuery, but that class is only some 9-10 lines of code, so you should be able to create a new class that implements IMethodQuery by using MockConstructorQuery as a starting point.
Likewise, you'll also need to create a custom ICustomization that does almost exactly the same as AutoMoqCustomization, with the only exception that it uses your custom IMethodQuery with strict mock configuration instead of MockConstructorQuery. That's another 7 lines of code you'll need to write.
All that said, in my experience, using strict mocks is a bad idea. It'll make your tests brittle, and you'll waste a lot of time mending 'broken' tests. I can only recommend that you don't do this, but now I've warned you; it's your foot.
For those interested, down below you can find #MarkSeemann's reply translated into code. I am pretty sure it does not cover all use cases and it was not heavily tested. But it should be a good starting point.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Moq;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Ploeh.AutoFixture.Kernel;
namespace ConsoleApplication1
{
public class StrictAutoMoqCustomization : ICustomization
{
public StrictAutoMoqCustomization() : this(new MockRelay()) { }
public StrictAutoMoqCustomization(ISpecimenBuilder relay)
{
// TODO Null check params
Relay = relay;
}
public ISpecimenBuilder Relay { get; }
public void Customize(IFixture fixture)
{
// TODO Null check params
fixture.Customizations.Add(new MockPostprocessor(new MethodInvoker(new StrictMockConstructorQuery())));
fixture.ResidueCollectors.Add(Relay);
}
}
public class StrictMockConstructorMethod : IMethod
{
private readonly ConstructorInfo ctor;
private readonly ParameterInfo[] paramInfos;
public StrictMockConstructorMethod(ConstructorInfo ctor, ParameterInfo[] paramInfos)
{
// TODO Null check params
this.ctor = ctor;
this.paramInfos = paramInfos;
}
public IEnumerable<ParameterInfo> Parameters => paramInfos;
public object Invoke(IEnumerable<object> parameters) => ctor.Invoke(parameters?.ToArray() ?? new object[] { });
}
public class StrictMockConstructorQuery : IMethodQuery
{
public IEnumerable<IMethod> SelectMethods(Type type)
{
if (!IsMock(type))
{
return Enumerable.Empty<IMethod>();
}
if (!GetMockedType(type).IsInterface && !IsDelegate(type))
{
return Enumerable.Empty<IMethod>();
}
var ctor = type.GetConstructor(new[] { typeof(MockBehavior) });
return new IMethod[]
{
new StrictMockConstructorMethod(ctor, ctor.GetParameters())
};
}
private static bool IsMock(Type type)
{
return type != null && type.IsGenericType && typeof(Mock<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && !GetMockedType(type).IsGenericParameter;
}
private static Type GetMockedType(Type type)
{
return type.GetGenericArguments().Single();
}
internal static bool IsDelegate(Type type)
{
return typeof(MulticastDelegate).IsAssignableFrom(type.BaseType);
}
}
}
Usage
var fixture = new Fixture().Customize(new StrictAutoMoqCustomization());

Mocking a base class method call with Moq

I am modifiying a class method which formats some input paramater dates which are subsequently used as params in a method call into the base class (which lives in another assembly).
I want to verify that the dates i pass in to my method are in the correct format when they are passed to the base class method so i would like to Moq the base class method call. Is this possible with Moq?
As of 2013 with latest Moq you can. Here is an example
public class ViewModelBase
{
public virtual bool IsValid(DateTime date)
{
//some complex shared stuff here
}
}
public class MyViewModel : ViewModelBase
{
public void Save(DateTime date)
{
if (IsValid(date))
{
//do something here
}
}
}
public void MyTest()
{
//arrange
var mockMyViewModel = new Mock<MyViewModel>(){CallBase = true};
mockMyViewModel.Setup(x => x.IsValid(It.IsAny<DateTime>())).Returns(true);
//act
mockMyViewModel.Object.Save();
//assert
//do your assertions here
}
If I understand your question correctly, you have a class A defined in some other assembly, and then an class B implemented more or less like this:
public class B : A
{
public override MyMethod(object input)
{
// Do something
base.MyMethod(input);
}
}
And now you want to verify that base.MyMethod is called?
I don't see how you can do this with a dynamic mock library. All dynamic mock libraries (with the exception of TypeMock) work by dynamically emitting classes that derive from the type in question.
In your case, you can't very well ask Moq to derive from A, since you want to test B.
This means that you must ask Moq to give you a Mock<B>. However, this means that the emitted type derives from B, and while it can override MyMethod (which is still virtual) and call its base (B.MyMethod), it has no way of getting to the original class and verify that B calls base.MyMethod.
Imagine that you have to write a class (C) that derives from B. While you can override MyMethod, there's no way you can verify that B calls A:
public class C : B
{
public override MyMethod(object input)
{
// How to verify that base calls its base?
// base in this context means B, not A
}
}
Again with the possible exception of TypeMock, dynamic mock libraries cannot do anything that you cannot do manually.
However, I would assume that calling the base method you are trying to verify has some observable side effect, so if possible, can you use state-based testing instead of behaviour-based testing to verify the outcome of calling the method?
In any case, state-based testing ought to be your default approach in most cases.
Agree with Mark, it's not possible using Moq.
Depending on your situation you may consider swithcing from inheritance to composition. Then you'll be able to mock the dependency and verify your method. Of course in some cases it just might not worth it.
wrap the base class method in a method and setup that method
e.g.
public class B : A
{
public virtual BaseMyMethod(object input)
{
// Do something
base.MyMethod(input);
}
public override MyMethod(object input)
{
// Do something
BaseMyMethod(input);
}
}
and now Setup the BaseMyMethod
It is quite possible mocking base class. But you will have to modify target class.
For ex. DerivedClass extends BaseClass.
BaseClass has methods MethodA(), MethodB(), MethodC()...
The DerivedClass has this method:
void MyMethod() {
this.MethodA();
this.MethodB();
this.MethodC();
}
You want to mock base class in order to validate that all MethodA(), MethodB(), MethodC() are being called inside MyMethod().
You have to create a field in the DerivedClass:
class DerivedClass {
private BaseClass self = this;
...
}
And also You have to modify the MyMethod():
void MyMethod() {
self.MethodA();
self.MethodB();
self.MethodC();
}
Also add a method, which can inject the this.self field with Mock object
public void setMock(BaseClass mock) {
this.self = mock;
}
Now you can mock:
DerivedClass target = new DerivedClass ();
BaseClass mock = new Mock(typeof(BaseClass));
target.setMock(mock);
target.MyMethod();
mock.verify(MethodA);
mock.verify(MethodB);
mock.verify(MethodC);
Using this technic, you can also mock nested method calls.
I found this solution - ugly but it could work.
var real = new SubCoreClass();
var mock = new Mock<SubCoreClass>();
mock.CallBase = true;
var obj = mock.Object;
mock
.Setup(c => c.Execute())
.Callback(() =>
{
obj.CallBaseMember(typeof(Action), real, "Execute");
Console.WriteLine(obj.GetHashCode());
}
);
public static Delegate CreateBaseCallDelegate(object injectedInstance, Type templateDelegate, object instanceOfBase, string methodName)
{
var deleg = Delegate.CreateDelegate(templateDelegate, instanceOfBase, methodName);
deleg.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(deleg, injectedInstance);
return deleg;
}
public static object CallBaseMember(this object injectedInstance, Type templateDelegate, object instanceOfBase, string methodName, params object[] arguments)
{
return CreateBaseCallDelegate(injectedInstance, templateDelegate, instanceOfBase, methodName).DynamicInvoke(arguments);
}

Resources