How do I mock HTTPSClient post service - http

I want to mock the following line of code:
ResponseEntity<String> response = client.callPostService(url, dto, new ParameterizedTypeReference<String>(){});
Attempt
#Test
public void testFunction{
HTTPSClient client = Mockito.mock(HTTPSClient.class);
Mockito.when(client.callPostService(any(String.class),any(Dto.class), new ParameterizedTypeReference<String>{}))
}
I get errors regarding the parameters I have placed.

You shouldn't mix Mockito's argument matchers (like any(), eq() etc.) and the real objects while configuring behavior for a mock.
So, in your case the next would be correct:
Mockito.when(client.callPostService(any(String.class),any(Dto.class), Mockito.any(ParameterizedTypeReference.class))).thenReturn(...)
or (since Java 8):
Mockito.when(client.callPostService(any(String.class),any(Dto.class), Mockito.any())).thenReturn(...)
The latter also doesn't raise the compiler warning about the unchecked cast of generic type because of enhanced type inference.

Related

ActivatorUtilities.CreateInstance giving "A suitable constructor not found" for simple examples

So I am building a complex case here with inheritance and IOC, need to use ActivatorUtilities to inject instances and pass parameters... no matter what I do I get the following error:
System.InvalidOperationException: 'A suitable constructor for type
'blabla.ISimpleTest' could not
be located. Ensure the type is concrete and all parameters of a public
constructor are either registered as services or passed as arguments.
Also ensure no extraneous arguments are provided.'
So in order to discard what could be the problem and ensure there is no constructor issues, I created a very very simple scenario that gives me the same error.
startup.cs
services.AddScoped<ISimpleTest, SimpleTest>();
the class and the interface, very simple here:
public interface ISimpleTest
{
}
public class SimpleTest : ISimpleTest
{
public SimpleTest()
{
}
}
test
var theInstance = ActivatorUtilities.CreateInstance<ISimpleTest>(ServiceProvider);
Additional notes
The ServiceProvider instance is fine (the rest/entire application depends on it).
Tried with and without adding the public constructor(empty params)
Tried also constructor with params, same error.
Tried to specify the params[] parameter, by sending null or empty array, same issue.
Extra test:
Just to confirm it's properly registered, I tried to get the instance using the Service provider, and works without issues:
//No issues this way:
var yyy = ServiceProvider.GetService<ISimpleTest>();
What am I doing here wrong? According to documentations, this should be enough to work

AutoFixture/AutoMoq: Unable to Create Instance (`BadImageFormatException`)

Below is a minimal example of the problem I am currently encountering:
using System.Net.WebSockets;
using AutoFixture;
using AutoFixture.AutoMoq;
using FluentAssertions;
using Xunit;
...
[Fact]
public void Test1()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization() { ConfigureMembers = true });
var sut = fixture.Create<WebSocket>();
sut.Should().NotBeNull();
}
[Fact]
public void Test2()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization() { ConfigureMembers = true });
var sut = new Mock<WebSocket>().Object;
fixture.Inject(sut);
sut.Should().NotBeNull();
}
...
When I run the first test, I get the following exception:
AutoFixture.ObjectCreationExceptionWithPath : AutoFixture was unable to create an instance from Moq.Mock`1[System.IO.Stream] because creation unexpectedly failed with exception. Please refer to the inner exception to investigate the root cause of the failure.
Inner exception messages:
System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
The second test succeeds.
I would like to be able to create an instance of a class using AutoFixture which takes a WebSocket as a constructor parameter, without the need to inject a mock object first (ultimately, so that I can use an AutoMoqData attribute, and get rid of some boilerplate). Have I got any misusage or misunderstanding going on here, or would this be better placed as a GitHub issue? In the interim, is there anything I can do to work around this issue?
You observe this issue because of the AutoFixture's factory discovery strategy. When you try to create an object of an abstract type, AutoFixture still inspects the type to find a static factory method to activate the object. In your particular case, the WebSocket type contains such methods, so some of them is used. It looks like it doesn't work well with auto-generated input values, so fails with an exception.
You can customize AutoFixture, to always mock the WebSocket type:
fixture.Register((Mock<WebSocket> m) => m.Object);
Just tested with the latest versions of products (AutoFixture 4.5.0, Moq 4.10.0) and it works like a charm.

Spring REST Exception Handling FileUploadBase$SizeLimitExceededException

I am using Spring Boot 1.5.3.RELEASE and using a Controller that takes a MultipartFile with some other information as arguments and returns a file.
Now I am facing the org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException when the file exceeds the maximum Sizes.
spring.http.multipart.maxFileSize=17728640
spring.http.multipart.maxRequestSize=17728640
This works well but i need a custom Response and actually the Exception is throwed only at server side before the method call.
Can anyone tell me how can I define a Custom Error Handler that handles this exception and response something like ResponseEntity.status(HttpStatus.CONFLICT).body("size_exceeded")
My Method:
#SuppressWarnings("rawtypes")
#RequestMapping(value = "/{Id}/attachments", method = RequestMethod.POST)
public ResponseEntity addTaskAttachment(#RequestParam("file") MultipartFile file, #PathVariable Long Id,
#CurrentUser User currentUser) {
// Some code here
ResponseEntity.status(HttpStatus.OK).body(attachmentAsByteArray);
}
You are correct in your observation that an Exception Handler with #RestControllerAdvice wouldn't work for multi part exceptions and reason being MultipartFile parsing & validation step preceding the mapping resolver step.
As advised in first accepted answer by geoand for this SO question here , you need to define and register an ErrorController.
Also, note that as already mentioned in that answer , Spring Boot already defines a BasicErrorController that you can extend to add new content types to return a JSON etc ( since default is text/html ) by adding a new public method with #RequestMapping & #Produces .

How can I let Rebus determine an endpoint for an interface and not for an implementation of that interface

When I Send an instance created by AutoMapper.Mapper.DynamicMap() I run into an error where Rebus seems to want to determine an endpoint for proxy type returned by DynamicMap. This instance will contain an implementation of T assuming T is an interface type.
Is there a way in which I can let Rebus determine an endpoint for the interface type T and not for the implementing type returned by DynamicMap()?
I tried playing around with IDetermineMessageOwnership but had no luck so far.
public static void Send<T>(this IBus bus, object source)
{
var message = Mapper.DynamicMap<T>(source);
bus.Send<T>(message);
}
Thanks in advance!
Sure! In your case, you could create your own implementation of IDetermineMessageOwnership which is the service that Rebus uses to map a message type to an endpoint.
If you want to leverage Rebus' existing logic, you could decorate any chosen strategy and extend it with a keep-looking-at-all-implemented-interfaces-until-one-can-be-mapped strategy like so:
Configure.With(adapter)
.(...)
.MessageOwnership(o => o.FromRebusConfigurationSection())
.Decorators(d => d.AddDecoration(DecorateOwnershipMapping)))
.CreateBus()
.Start();
where DecorateOwnershipMapping would install a decorator on top of whatever is configured like so:
void DecorateOwnershipMapping(ConfigurationBackbone b)
{
b.DetermineMessageOwnership = new CustomizedEndpointMapper(b.DetermineMessageOwnership);
}
and a possible implementation could look like this:
class CustomizedEndpointMapper : IDetermineMessageOwnership
{
readonly IDetermineMessageOwnership wrappedEndpointMapper;
public CustomizedEndpointMapper(IDetermineMessageOwnership wrappedEndpointMapper)
{
this.wrappedEndpointMapper = wrappedEndpointMapper;
}
public string GetEndpointFor(Type messageType)
{
var mappingCandidates = new[] {messageType}
.Concat(messageType.GetInterfaces())
.ToList();
foreach (var typeToTry in mappingCandidates)
{
try
{
return wrappedEndpointMapper.GetEndpointFor(typeToTry);
}
catch{}
}
throw new InvalidOperationException(string.Format("Could not determine the owner of message of type {0} - attempted to map the following types: {1}",
messageType, string.Join(", ", mappingCandidates)));
}
}
thus iterating through the concrete type as well as all inherited interface types when trying to determine the owning endpoint.
In your case, I believe this would work flawlessly when determining the message owner. Only problem is that the serializer will most likely complain, because the dynamically generated type cannot be recognized again when the message is received.
Hence, this trick requires customization of the serializer as well. If you're using the (default) JSON serializer, you might get away with some custom resolvers like so:
Configure.With(...)
.(...)
.Serialization(s => s.UseJsonSerializer()
.AddNameResolver(CustomNameResolver)
.AddTypeResolver(CustomTypeResolver))
.(...)
where CustomNameResolver and CustomTypeResolver are methods that must then take care of mapping the type to a type name and mapping the type name to a type that can then be deserialized into. In order to make this work with AutoMapper, you'll probably need to either
a) somehow use AutoMapper to look up the type of the received message and return that type from CustomTypeResolver, or
b) customize the serializer to have AutoMapper somehow participate in generating the object to be returned
but I must admit that I'm unsure whether the last part will play out smoothly.
A final note: if you succeed in making this work, I suggest you pack up your configuration spells into a reusable extension method on RebusConfigurer so that your endpoints can just go
Configure.With(...)
.(...)
.UseMyFunkyAutoMapperMessagesJustTheWayILikeIt()
.CreateBus().Start();
in all your Rebus endpoints...
I'll appreciate it if you'll let me know how this works out for you! :)

TypeLoadException when trying to mock IObjectSet with Moq

I have the following setup code:
MockOf<IObjectSet<Dummy>>().Setup(c => c.AddObject(dummy)).Verifiable();
MockOf<IObjectContextWrapper>().Setup(c => c.GetObjectSet<Dummy>()).Returns(MockOf<IObjectSet<Dummy>>().Object);
where Dummy is an empty class definition, and dummy is a Dummy. MockOf<T>() is a mock managing feature on a base class, which basically makes sure that each time it's called on a type, it returns the same mock instance.
The test containing this setup code fails with a TypeLoadException and the following message:
System.TypeLoadException : Type 'IObjectSet`1Proxy389e220f10aa4d9281d0b9e136edc1d4' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69' is attempting to implement an inaccessible interface.
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
at Moq.Mock1.<InitializeInstance>b__0()
at Moq.Mock1.InitializeInstance()
at Moq.Mock`1.get_Object()
at OddEnds.Tests.Data.EntityFramework.RepositoryTest.Delete_DeletesObjectFromObjectSet() in RepositoryTest.cs: line 43
I have imported System.Data.Objects and referenced both System.Data.Entity.dll and Microsoft.Data.Entity.CTP.dll in both the test project and the project where the class being tested resides. The build succeeds with no errors, warnings or messages (except a few related to Code Contracts...)
How do I fix this?
Are any of the interfaces or class you are using in your tests internal? Are you using something like [assembly: InternalsVisibleTo("YourTestAssembly")] in order to get things to compile?
If so, you'll also need to add one for DynamicProxyGenAssembly2 in order for Moq to dynamically generate the proxy for the classes.
//goes in the AssemblyInfo.cs where the internal interfaces / classes are defined
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Here is a relevent post about the topic
http://sonofpirate.blogspot.com/2009/09/my-first-foray-into-unit-testing-with.html
I hope this helps
I found that in my case I had created a Dummy class instance to be used in my unit test which happened to be private (as I didn't really want to share the test object outside).
My code was along these lines:
var mockMonitor = new Mock<ICacheMonitor<int, PrivateObject>>();
where the PrivateObject was a private class definition within my TestClass.
The fix in my case is therefore to ensure that any of the types in your Mock constructor are public.
public class PrivateObject () {}
(Obviously I wouldn't call my public object a PrivateObject either...)
I tripped across another case which I couldn't figure out at first. I was working on a proxy for an interface created inside of my unit test...
public IDoWork
{
void DoWork();
}
It took me forever to figure out that the problem was not with that interface, but was, rather, that the unit test itself was not public:
class TestSomething // missing public keyword
{
// .. some test which tries to create a mock of the interface
public IDoWork
{
void DoWork();
}
}
So, while IDoWork is says it's public, it really is not since it's enclosed in a private class.
Hope this helps someone.

Resources