Mock Generic Method with Type Variable - NSubstitute - unit-testing

I have a client interface that looks like this:
public interface IDiscosClient
{
public Task<DiscosResponse<T>?> Get<T>(string queryUrl) where T : DiscosModelBase;
// The rest
}
And DiscosResponse<T> looks like this:
public record DiscosResponse<T> where T: DiscosModelBase
{
public DiscosResponse()
{
}
internal DiscosResponse(T attributes)
{
Attributes = attributes;
}
[JsonPropertyName("type")]
public ResponseType Type { get; init; }
// TODO - This is wrong an probably needs renaming to something like Object
[JsonPropertyName("attributes")]
public T Attributes { get; init; }
[JsonPropertyName("id")]
[JsonConverter(typeof(JsonStringIntConverter))]
public int Id { get; init; }
}
I want to be able to be able to dynamically create a Substitute.For<T>() of this interface that will always build and return an instance of T.
So I know how to construct and call a generic method. I also have AutoFixture set up so that I can create new instances of T on demand.
What I don't know, however, is how to then go about telling NSubstitute to return this new instance when this constructed method is called.
For reference, the usual syntax for doing this without reflection would be:
MyType myMock = Substitute.For<MyType>();
myMock.MyMethod().Returns(myInstance);
Edit:
I've had to put a pin in the AutoFix part of this because it was causing recursion issues. However, I've now come up with this, which seems to work right up until I try and set the return value on the invocation:
private IDiscosClient CreateSubstituteClient(Type type)
{
IDiscosClient client = Substitute.For<IDiscosClient>();
MethodInfo getMethod = typeof(IDiscosClient).GetMethod(nameof(client.Get), new [] {typeof(string)}) ?? throw new MethodAccessException();
MethodInfo constructedGetMethod = getMethod.MakeGenericMethod(type);
Type constructedReturnType = typeof(DiscosResponse<>).MakeGenericType(type);
const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
CultureInfo culture = CultureInfo.InvariantCulture;
object returnValue = Activator.CreateInstance(constructedReturnType, flags, null, new [] {Activator.CreateInstance(type)}, culture); // Not using AutoFix as it will cause recursion issues
constructedGetMethod.Invoke(client, new object?[] {Arg.Any<string>()}).Returns(Task.FromResult(returnValue));
return client;
}
At which point it throws this error:
NSubstitute.Exceptions.CouldNotSetReturnDueToTypeMismatchException:
Can not return value of type Task1 for IDiscosClient.Get (expected type Task1).
Which is confusing because the type of returnValue is:
DISCOSweb_Sdk.Models.DiscosResponse`1[[DISCOSweb_Sdk.Models.ResponseModels.Reentries.Reentry,
DISCOSweb-Sdk, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]], DISCOSweb-Sdk, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null
And constructedGetMethod.ReturnParameter is:
System.Threading.Tasks.Task1[DISCOSweb_Sdk.Models.DiscosResponse1[DISCOSweb_Sdk.Models.ResponseModels.Reentries.Reentry]]
Which, AFIACT match once I wrap the former in a Task.FromResult

Task.FromResult(returnValue) results in runtime type of Task<object> while your method expects Task<DiscosResponse<T>?>. NSubstitute checks compatibility of returned type with(among others) IsAssignableFrom so it throws exception. In this particular case you need to do sth like this
var methodInfo = typeof(Task).GetMethod(nameof(Task.FromResult), BindingFlags.Static | BindingFlags.Public);
var fromResult = methodInfo.MakeGenericMethod(constructedReturnType).Invoke(null, new []{ returnValue});
constructedGetMethod.Invoke(client, new object?[] {Arg.Any<string>()}).Returns(fromResult);
in order for runtime types to be the same.

Related

Roslyn / IPropertySymbol / arrary return type

I'm trying to return all the properties of a class, and the return type of each property using Roslyn (not reflection..)
I've gotten close, but then I hit a property that returns an array of strings (or perhaps an enumeration?) I'm fighting with how to find out the type within the array/collection...
public class msgClass // part of a larger class, and referenced as Roslyn Document
string[] Lines {get; set;} //property in larger class of properties
...
var DocumentsInProject = await roslynUtilities.GetMembers<BasePropertyDeclarationSyntax>(msgClass);
foreach (var itemClassProperty in DocumentsInProject)
{
var itemDeclaredSymbol = semanticModelOfDoc
.GetDeclaredSymbol(itemClassProperty) as IPropertySymbol;
if (itemDeclaredSymbol == null)
throw new Exception($"property: {itemClassProperty}");
var name = itemDeclaredSymbol.Name;
//what does it return?
string returnType = string.Empty;
if (itemDeclaredSymbol.Type.IsReferenceType)
{
var typeofKind = itemDeclaredSymbol.Type.TypeKind;
var typeincollection = itemDeclaredSymbol.Type.BaseType;
var containingType = itemDeclaredSymbol.Type.ContainingType.Name;
}
else
{
returnType = itemDeclaredSymbol.Type.Name;
}
}
If it isn't obvious this is isn't production code - I'm hacking as I'm new to Roslyn, and I'm working on building a Visual Studio add-in that is reviewing classes in a project.
You actually need to convert property type symbol to INamedTypeSymbol or to IArrayTypeSymbol. You can check that the type is generic [un]bound type by INamedTypeSymbol and try to figure out the generic type parameters. It will allow to you receive collection's element type if type not just generic type, but collection. Casting to IArrayTypeSymbol will allow to you get array's element type. So your code should look like this:
...
if (itemDeclaredSymbol.Type is INamedTypeSymbol namedType && namedType.IsGenericType)
{
// use namedType.TypeArguments if type is bound generic or namedType.TypeParameters if isn't
}
else if (itemDeclaredSymbol.Type is IArrayTypeSymbol arrayType)
{
// use arrayType.ElementType as you want
}
...

Creating a fallback container/resolver DryIoc

Current working on creating a Prism.DryIoc.Forms project to try out DryIoc (first time!).
In Xamarin.Forms there is a native DependencyService and to provide a nice way to migrate towards using Prism I would like to add it as a fallback container in case the requsted service type can't be resolved from the main container.
Current I have created a FallbackContainer and pass the instance of IContainerand overrides the methods for IResolver and delegates the rest of the IContainer calls to the instance passed during creation.
So after the default container is created and configured and then do
Container = CreateContainer();
ConfigureContainer();
Container.Rules.WithFallbackContainer(new DependencyServiceContainer(Container));
Is this the preferred method or is there any way just to attach a default IResolver?
Current implementation
public class FallbackDependencyServiceContainer : IContainer
{
private readonly IContainer container;
public FallbackDependencyServiceContainer(IContainer container)
{
this.container = container;
}
public object Resolve(Type serviceType, bool ifUnresolvedReturnDefault)
{
return ResolveFromDependencyService(serviceType);
}
public object Resolve(Type serviceType, object serviceKey, bool ifUnresolvedReturnDefault,
Type requiredServiceType,
RequestInfo preResolveParent, IScope scope)
{
return ResolveFromDependencyService(serviceType);
}
public IEnumerable<object> ResolveMany(Type serviceType, object serviceKey, Type requiredServiceType,
object compositeParentKey,
Type compositeParentRequiredType, RequestInfo preResolveParent, IScope scope)
{
return new[] { ResolveFromDependencyService(serviceType) };
}
private static object ResolveFromDependencyService(Type targetType)
{
if (!targetType.GetTypeInfo().IsInterface)
{
return null;
}
var method = typeof(DependencyService).GetTypeInfo().GetDeclaredMethod("Get");
var genericMethod = method.MakeGenericMethod(targetType);
return genericMethod.Invoke(null, new object[] { DependencyFetchTarget.GlobalInstance });
}
....
}
Thanks and looking forward to test DryIoc since I've read it's supposed to be the fastest out there
Updated answer:
You may directly use WithUnknownServiceResolvers returning DelegateFactory:
var c = new Container(Rules.Default.WithUnknownServiceResolvers(request =>
new DelegateFactory(_ => GetFromDependencyService(request.ServiceType))));
No need to implement IContainer just for that.
I think it may be optimized regarding performance by replacing DelegateFactory with ExpressionFactory. But I need some time to play with the idea.

Mockito - how to mock/verify a method call which accepts a new object?

I have a method (method1) that I'd like to test, which based on parameters provided creates an object and calls another method (method2). So I'm mocking method2, which accepts an object (sampleObj).
public void method1(booleanParam) {
if(booleanParam){
List<SampleObj> fooList = new ArrayList<SampleObj>;
fooList.add(new SampleObj("another param"));
anotherService.method2(fooList);
}
//some other smart logic here
}
And here's my test with same obfuscated names (sorry if I missed any typo):
public void testMethod1() {
AnotherService mockedAnotherService = PowerMockito.mock(AnotherService.class);
ServicesFactory.getInstance().setMock(AnotherService.class, mockedAnotherService);
List<SampleObj> fooList = new ArrayList<SampleObj>;
fooList.add(new SampleObj("another param"));
// assert and verify
service.method1(true);
Mockito.verify(mockedAnotherService, times(1)).method2(fooList);
}
The problem is, when I try to mock the anotherService, I need to pass an object to method2, so I have to create a new one. But since it's a new object, it's not the same object, which will be passed from inside the method1, hence the test fails with the exception:
Argument(s) are different! Wanted:
anotherService.method2(
[com.smart.company.SampleObj#19c59e46]
);
-> at <test filename and line # here>
Actual invocation has different arguments:
anotherService.method2(
[com.smart.company.SampleObj#7d1a12e1]
);
-> at <service filename and line # here>
Any ideas how to accomplish that?
You have a few options:
Implement equals and hashCode on SampleObj. Because you didn't wrap fooList in a matcher, Mockito checks with List.equals, which checks equals for corresponding objects in each List. The default behavior of Object.equals is that a.equals(b) iff a == b--that is, objects are equal iff they refer to the same instance--but you're welcome to override that if every SampleObj("foobar") equals every other SampleObj("foobar").
Use a Hamcrest Matcher you write.
private static Matcher<List<SampleObj>> isAListWithObjs(String... strings) {
return new AbstractMatcher<List<SampleObj>>() {
#Override public boolean matches(Object object) {
// return true if object is a list of SampleObj corresponding to strings
}
};
}
// in your test
verify(mockedAnotherService).method2(argThat(isAnObjListWith("another param")));
Note that you could also just make a Matcher of a single SampleObj, and then use a Hamcrest wrapper like hasItem. See more matchers here.
Use a Captor to check equals your own way:
public class YourTest {
// Populated with MockitoAnnotations.initMocks(this).
// You can also use ArgumentCaptor.forClass(...), but with generics trouble.
#Captor ArgumentCaptor<List<SampleObj>> sampleObjListCaptor;
#Test public void testMethod1() {
// ...
verify(mockedAnotherService).method2(sampleObjListCaptor.capture());
List<SampleObj> sampleObjList = sampleObjListCaptor.getValue();
assertEquals(1, sampleObjList.size());
assertEquals("another param", sampleObjList.get(0).getTitle());
}

Derived Class Method of Generic Class Template not being called

I have a generic class for making and processing JSON API requests. I pass in the TParam and TResult template parameters but when I use a derived type it's implementation is not being called.
Here is some code you can throw in a playground to illustrate:
import Cocoa
// Base class for parameters to POST to service
class APIParams {
func getData() -> Dictionary<String, AnyObject> {
return Dictionary<String, AnyObject>()
}
}
// Base class for parsing a JSON Response
class APIResult {
func parseData(data: AnyObject?) {
}
}
// Derived example for a login service
class DerivedAPIParams: APIParams {
var user = "some#one.com"
var pass = "secret"
// THIS METHOD IS CALLED CORRECTLY
override func getData() -> Dictionary<String, AnyObject> {
return [ "user": user, "pass": pass ]
}
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
var success = false
var token:String? = ""
// THIS METHOD IS NEVER CALLED
override func parseData(data: AnyObject?) {
/*
self.success = data!.valueForKey("success") as Bool
self.token = data!.valueForKey("token") as? String
*/
self.success = true
self.token = "1234"
}
}
class APIOperation<TParams: APIParams, TResult: APIResult> {
var url = "http://localhost:3000"
func request(params: TParams, done: (NSError?, TResult?) -> ()) {
let paramData = params.getData()
// ... snip making a request to website ...
let result = self.parseResult(nil)
done(nil, result)
}
func parseResult(data: AnyObject?) -> TResult {
var result = TResult.self()
// This should call the derived implementation if passed, right?
result.parseData(data)
return result
}
}
let derivedOp = APIOperation<DerivedAPIParams, DerivedAPIResult>()
let params = DerivedAPIParams()
derivedOp.request(params) {(error, result) in
if result? {
result!.success
}
}
The really weird thing is that only the DerivedAPIResult.parseData() is not called, whereas the DerivedAPIParams.getData() method is called. Any ideas why?
UPDATE: This defect is fixed with XCode 6.3 beta1 (Apple Swift version 1.2 (swiftlang-602.0.37.3 clang-602.0.37))
Added info for a workaround when using XCode 6.1 (Swift 1.1)
See these dev forum threads for details:
https://devforums.apple.com/thread/251920?tstart=30
https://devforums.apple.com/message/1058033#1058033
In a very similar code sample I was having the exact same issue. After waiting through beta after beta for a "fix", I did more digging and discovered that I can get the expect results by making the base class init() required.
By way of example, here is Matt Gibson's reduced example "fixed" by adding the proper init() to ApiResult
// Base class for parsing a JSON Response
class APIResult {
// adding required init() to base class yields the expected behavior
required init() {}
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
}
class APIOperation<TResult: APIResult> {
init() {
// EDIT: workaround for xcode 6.1, tricking the compiler to do what we want here
let tResultClass : TResult.Type = TResult.self
var test = tResultClass()
// should be able to just do, but it is broken and acknowledged as such by Apple
// var test = TResult()
println(test.self) // now shows that we get DerivedAPIResult
}
}
// Templated creation creates APIResult
let derivedOp = APIOperation<DerivedAPIResult>()
I do not know why this works. If I get time I will dig deeper, but my best guess is that for some reason having required init is causing different object allocation/construction code to be generated that forces proper set up of the vtable we are hoping for.
Looks possibly surprising, certainly. I've reduced your case to something rather simpler, which might help to figure out what's going on:
// Base class for parsing a JSON Response
class APIResult {
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
}
class APIOperation<TResult: APIResult> {
init() {
var test = TResult()
println(test.self) // Shows that we get APIResult, not DerivedAPIResult
}
}
// Templated creation creates APIResult
let derivedOp = APIOperation<DerivedAPIResult>()
...so it seems that creating a new instance of a templated class with a type constraint gives you an instance of the constraint class, rather than the derived class you use to instantiate the specific template instance.
Now, I'd say that the generics in Swift, looking through the Swift book, would probably prefer you not to create your own instances of derived template constraint classes within the template code, but instead just define places to hold instances that are then passed in. By which I mean that this works:
// Base class for parsing a JSON Response
class APIResult {
}
// Derived example for parsing a login response
class DerivedAPIResult: APIResult {
}
class APIOperation<T: APIResult> {
var instance: T
init(instance: T) {
self.instance = instance
println(instance.self) // As you'd expect, this is a DerivedAPIResult
}
}
let derivedOpWithPassedInstance = APIOperation<DerivedAPIResult>(instance: DerivedAPIResult())
...but I'm not clear whether what you're trying should technically be allowed or not.
My guess is that the way generics are implemented means that there's not enough type information when creating the template to create objects of the derived type from "nothing" within the template—so you'd have to create them in your code, which knows about the derived type it wants to use, and pass them in, to be held by templated constrained types.
parseData needs to be defined as a class func which creates an instance of itself, assigns whatever instance properties, and then returns that instance. Basically, it needs to be a factory method. Calling .self() on the type is just accessing the type as a value, not an instance. I'm surprised you don't get some kind of error calling an instance method on a type.

Verify method was called with certain linq expression (moq)

Can't figure out the syntax.
//class under test
public class CustomerRepository : ICustomerRepository{
public Customer Single(Expression<Func<Customer, bool>> query){
//call underlying repository
}
}
//test
var mock = new Mock<ICustomerRepository>();
mock.Object.Single(x=>x.Id == 1);
//now need to verify that it was called with certain expression, how?
mock.Verify(x=>x.Single(It.Is<Expression<Func<Customer, bool>>>(????)), Times.Once());
Please help.
Hmmm, you can verify that the lambda is being called by creating a mock for an interface that has a method matching the lambda parameters and verifying that:
public void Test()
{
var funcMock = new Mock<IFuncMock>();
Func<Customer, bool> func = (param) => funcMock.Object.Function(param);
var mock = new Mock<ICustomerRepository>();
mock.Object.Single(func);
funcMock.Verify(f => f.Function(It.IsAny<Customer>()));
}
public interface IFuncMock {
bool Function(Customer param);
}
The above might or might not work for you, depending on what Single method does with the Expression. If that expression gets parsed into SQL statement or gets passed onto Entity Framework or LINQ To SQL then it'd crash at runtime. If, however, it does a simple compilation of the expression, then you might get away with it.
The expression compilation that I spoke of would look something like this:
Func<Customer, bool> func = Expression.Lambda<Func<Customer, bool>>(expr, Expression.Parameter(typeof(Customer))).Compile();
EDIT If you simply want to verify that the method was called with a certain expression, you can match on expression instance.
public void Test()
{
Expression<Func<Customer, bool>> func = (param) => param.Id == 1
var mock = new Mock<ICustomerRepository>();
mock.Object.Single(func);
mock.Verify(cust=>cust.Single(func));
}