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.
Related
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.
I'm quite new to Swift and recently noticed that you cannot inherit from a generic in Swift, e.g.
class MyClass<T> : T {}
is not valid in Swift 3 (see question this question).
Here is the problem I was hoping to solve with the above construct:
protocol Backend {
func operationA(operand: Int)
}
class ConcreteBackend : Backend {
func operationA(operand: Int) {
// ...
}
// Some other functions and/or custom initializers
// ...
}
class EnhancedBackend<T : Backend> : T {
override func operationA(operand: Int) {
// do something smart here
super.operationA(operand: modifiedOperand)
}
}
Basically EnhancedBackend does something smart with the input of operationA and then passes it to the actual implementation of Backend.
I'm using inheritance here instead of composition, because ConcreteBackend might have some public properties, functions and initializers that are not specified in the protocol (because they are only related to the concrete implementation) that I want to also expose with EnhancedBackend.
Without inheritance this would not be possible.
A C++ implementation might look like
// Using concepts here instead of protocols
class ConrecteBackend {
public:
void operationA(int operand) { .... }
}
template<class T>
class EnhancedBackend : public T {
using Base = T;
public:
// Ensure T is a model of the Backend concept
static_assert(isModelOfConceptBackend<T>::value,
"Template parameter is not a model of concept Backend");
// Ensure all constructors of Base can be used
template<class ...Args, typename = std::enable_if_t<
std::is_constructible<Base, Args...>::value>>
inline EnhancedBackend(Args &&...args) : Base(std::forward<Args>(args)...) {}
void operationA(int operand) {
// ...
Base::operationA(operand);
}
};
So with C++ it's quite simple to solve the problem. But at the moment I have no clue how to implement in with (pure) Swift 3.
Swift's generics are not the same as C++ templates which are closer to pre processing macros than Swift's type semantics.
There are however a number of ways to achieve similar results. One way if to use variables to reference functions that need customized dispatching rules:
for example:
protocol Backend:class
{
var operationA:(Int) -> () { get set }
func performOperationA(_ : Int) -> ()
}
class ConcreteBackend : Backend
{
lazy var operationA:(Int) -> () = self.performOperationA
func performOperationA(_ : Int) -> ()
{
// ...
}
// Some other functions and/or custom initializers
// ...
}
extension Backend
{
var enhancedForTesting:Self
{
operationA = testing_OperationA
return self
}
func testing_OperationA(_ operand:Int) -> ()
{
let modifiedOperand = operand + 1
performOperationA(modifiedOperand)
}
}
let enhancedBackend = ConcreteBackend().enhancedForTesting
By using a variable to reference the function's implementation, it becomes possible to dynamically change the behaviour of operationA at runtime and for specific instances.
In this example, the enhancements are added to the Backend protocol but they could also have been set by an independent function or even another class that has its own particular kind of altered behaviour.
When using this approach, the instance has all the attributes and functions of the concrete class while implementing the enhanced behaviour for the altered functions of the protocol.
Creating the enhanced instance uses a syntax that is as simple as (if not simpler than) a generic class constructor:
// for example:
let instance = ConcreteBackend(...).enhanced
// rather than:
let instance = EnhancedBackend<ConcreteBackEnd>(...)
Suppose I have the following classes:
public class Setup { }
public class Configuration<T> where T : class
{
internal Configuration(Setup setup) { }
}
public class Process<T> where T : class
{
internal Process(Configuration<T> configuration) { }
}
I want to register these classes in DryIoc and need each Process<T> to be singleton (as would be Configuration<T>). So, Process<ClassA> would resolve the same instance, and Process<ClassB> will do the same. But Process<ClassA> and Process<ClassB> would be 2 different instances.The same applies to Configuration<T>.How would I register these 3 classes to achieve what I need?Note that constructors are internal.
This is what I've done without success:
var container = new Container();
container.Register<Setup>(Reuse.Singleton);
container.Register(typeof (Configuration<>),
made: Made.Of(typeof (Configuration<>).GetConstructorOrNull(true, typeof (Setup))));
container.Register(typeof(Process<>), Reuse.Singleton,
Made.Of(typeof(Process<>).GetConstructorOrNull(true, typeof(Configuration<>))));
I get: "An exception of type 'System.NullReferenceException' occurred in DryIoc.dll but was not handled in user code" when, as an example I dovar a = container.Resolve<Process<EventArgs>>();
The problem is with getting constructor from generic type. For now you may use DryIoc API to get ConstructorWithResolvableArgumentsIncludingNonPublic:
Working sample looks like that:
var container = new Container();
container.Register<Setup>(Reuse.Singleton);
container.Register(typeof(Configuration<>), Reuse.Singleton,
made: FactoryMethod.ConstructorWithResolvableArgumentsIncludingNonPublic);
container.Register(typeof(Process<>), Reuse.Singleton,
FactoryMethod.ConstructorWithResolvableArgumentsIncludingNonPublic);
var p = container.Resolve<Process<EventArgs>>();
In future versions it will be more simple like FactoryMethod.Constructor(includeNonPublic: true).
Update with workaround:
This is an actual issue in DryIoc 2.9.7 with creating singletons with internal constructor. The fix is on the way. For now you can use a workaround by disabling certain singleton optimizations with rule:
var container = new Container(rules => rules.WithoutEagerCachingSingletonForFasterAccess());
Updated live sample.
Update with fix:
The problem is fixed in DryIoc 2.10
I am new to FakeItEasy and try solve a problem.
I have a class
public class Events
{
public List<Events> SaveEvents()
{
// Call to repository and return 1(success) or -1(fail)
//If the repository return 1 then need to make another call to save the action in db
//Sample Code here
AuditLogService log = new AuditLogService();
log.CallLog();
}
}
Here is the Test Code:
[TestMethod]
public void EventValidation()
{
//Arrange
var Fakeevents = A.Fake<Events>();
var log = A.Fake<AuditLogService>();
var _EventsController = new EventsController(Fakeevents);
_EventsController.SaveEvents();
A.CallTo(
() => Fakeevents.SaveEvents().Retunr(1).AssignsOutAndRefParameters(status)
A.CallTo(
() => log.CallLog()).MustHaveHappened(Repeated.AtLeast.Once);
}
I am getting error like "Non virtual methods can not be intercepted"
I want to check whether the Calllog method is called after success or not.
Can anyone please help me on this.
I have a method and inside a method i am initiating another class and calling a method of the class. I want to check from fakeItEasy whether the method is called.
Unfortunately, your title says it all. Non-virtual members cannot be faked, configured, or intercepted, as noted in the documentation under "What members can be overridden?".
There's nothing that FakeItEasy can do for you unless you make the member virtual (or promote it to an interface and fake the interface, or something similar).
Have you tried to use function?
Like this:
Func<YourReturnType> action = () => YourMethod(params); // Act
action.Should().Throw<Exception>(); // Assert
var log = A.Fake();
Use interface instead of AuditLogService. And have this class implement that interface
var log = A.Fake();
using [assembly:InternalsVisibleTo()] and
public sealed class AppService
{
//TODO: fix dev's spelling
//want to test this
public AddSubscribtionResponse AddSubscribtion(AddSubscribtionRequest request)
{
return ExecuteQueryProc<AddSubscribtionResponse>("spAddAppToUserGroup", request).First();
}
//I want to stub or interaction test the call to here
#if DEBUG
internal
#endif
List<T> ExecuteQueryProc<T>(string query, object parameters = null)
{
var cn=GetConnection();
//DatabaseCommand is a static class =(
return DatabaseCommand.ExecuteQueryProc<T>(cn, query, parameters);
}
}
Every attempt I've made at getting Rhino to stub or intercept the Execute Query proc method has failed.
var service = MockRepository.GeneratePartialMock<AppService>(null);
service.Stub(f => f.ExecuteQueryProc<AddSubscribtionRequest>(null, null)).IgnoreArguments().Return(new List<AddSubscribtionRequest>());
var expected = new AddSubscribtionRequest();
var actual = service.AddSubscribtion(expected);
Throws
System.InvalidOperationException: ExecuteReader: CommandText property has not been initialized
Remove the "sealed" from your class (Rhino.Mocks can't proxy your class if it can't inherit from it). And ExecuteQueryProc has to be virtual to be able to stub its functionality.