Methods in Default Protocol extension executed on unit testing always - ios

I have a protocol with the default implementation in the extension of that protocol. When I try to create a concrete mock object of that protocol to unit test, the default implementation always gets executed. I am not able to figure why. Any help would be appreciated. I am on xcode 11.3
protocol ABC: AnyObject {
func doSomething()
}
extension ABC {
func doSomething() {
print("Did Something")
}
}
final class ClassToBeTested {
var abc: ABC?
func methodToBeTested() {
abc?.doSomething()
}
}
In Test Target
final class MockABC: ABC {
func doSomething() {
print("Did Something in Test Target")
}
}
final class Tests: XCTestCase {
func testMethod() {
let obj = ClassTobeTested()
// abc property is of type protocol ABC
obj.abc = MockABC()
*This line calls the default implementation of the protocol of ABC and not the
implementation in MockABC class - verifiable by breakpoints and print statements*
obj.methodToBeTested()
}
}
I have read the static dispatch which happens in such cases, but could not find any particular reason to this. Kindly help.

You need to inject the protocol.
protocol ABC: AnyObject {
func doSomething() -> String
}
extension ABC {
func doSomething() -> String {
return "Did Something"
}
}
final class ClassToBeTested {
private let abc: ABC
init(abc: ABC) {
self.abc = abc
}
func methodToBeTested() -> String {
return abc.doSomething()
}
}
Testing Target
final class ABCMock: ABC {
func doSomething() {
print("Did Something in Test Target")
}
}
final class ClassToBeTestedTests: XCTestCase {
private let mockABC: MockABC = .init()
func test_methodToBeTested() {
let obj = ClassTobeTested()
XCTAssertEqual(obj.methodToBeTested(), "Did Something in Test Target")
}
}
This snippet of code it's very simple, but according to your question this is the best way.

Related

Is this the correct way to write unit test for Interactor in VIPER, swift, iOS?

I have a small sorting function in the Interactor which takes a set of Strings and sort it and notify to the Presenter. That function works as expected.
Now I'm just trying cover that function with unit test. so I created a Unit Test Class for my Interactor and Mocked the Interactor Output and did the test like below. am I doing it right?
shouldn't we end the test inside the testFunction, in this case
inside the testSortFunction()
This triggers notifySortedNames() in the Mock Interactor Output Class and I tested the use case inside that. I guess this is the wrong way.
How can I achieve the testing of this scenario inside the testFunction()? I'd appreciate your help with this.
Interactor
class DetailInteractor: DetailInteractorInput {
var output: DetailInteractorOutput?
init(output: DetailInteractorOutput) {
self.output = output
}
func sortNames(names: [String]) {
let sorteNames = names.sorted(by: { $0 < $1 })
output?.notifySortedNames(names: sorteNames)
}
}
Interactor Test Class
import XCTest
#testable import UnitTesst
class DetailInteractorTest: XCTestCase {
var interactor: DetailInteractor!
var output: DetailInteractorOutput!
override func setUpWithError() throws {
output = DetailInteractorOutputMock()
interactor = DetailInteractor(output: output)
}
override func tearDownWithError() throws {
}
func testSortFunction() throws {
let names = ["Japan", "France", "Australia"]
interactor.sortNames(names: names)
}
func testPerformanceExample() throws {
self.measure {
}
}
}
// Mock Test Classes
class DetailInteractorOutputMock: DetailInteractorOutput {
func notifySortedNames(names: [String]) {
let expected = ["Australia", "France", "Japan"]
XCTAssertEqual(expected[0], names[0])
XCTAssertEqual(expected[1], names[1])
XCTAssertEqual(expected[2], names[2])
}
}
Thanks!!

Call a method with dynamic class name in swift

How can we call class functions with a dynamic class name?
Assume the following example where I have two class with methods with same signature
class Foo{
class func doSomething()
}
class Foobar {
class func doSomething()
}
class ActualWork{
//call following method with a variable type so that it accepts dynamic class name
func callDynamicClassMethod(x: dynamicClass)
x.doSomething()
}
How can this be implemented so that x accepts values at run time
Edit: Sorry, I missed to mention that I was looking for any other ways other than protocol oriented approach. This is more of an exploratory question to explore if there is a more direct approach/pods/libraries to achieve this.
I liked this question, because it made me to think a lit'bit outside of the box.
I'll answer it, by dividing it into a few parts.
First
call class functions
Class function is basically a Type methods, which can be achieved using the static word inside the class context.
Taking that into account, you can get a simple solution, using protocol and passing the class reference (conforming to that protocol) like this:
protocol Aaa{
static func doSomething();
}
class Foo : Aaa{
static func doSomething() {
print("Foo doing something");
}
}
class FooBar : Aaa{
static func doSomething() {
print("FooBar doing something");
}
}
class ActualWork{
//Using class (static) method
func callDynamicClassMethod <T: Aaa> (x: T.Type) {
x.doSomething();
}
}
//This is how you can use it
func usage(){
let aw = ActualWork();
aw.callDynamicClassMethod(x: Foo.self);
aw.callDynamicClassMethod(x: Foo.self);
}
Second
In case you don't really need the method on the class context, you may consider using instance methods. In that case the solution would be even simpler, like this:
protocol Bbb{
func doSomething();
}
class Bar : Bbb{
func doSomething() {
print("Bar instance doing something");
}
}
class BarBar : Bbb{
func doSomething() {
print("BarBar instance doing something");
}
}
class ActualWork{
//Using instance (non-static) method
func callDynamicInstanceMethod <T: Bbb> (x: T){
x.doSomething();
}
}
//This is how you can use it
func usage(){
let aw = ActualWork();
aw.callDynamicInstanceMethod(x: Bar());
aw.callDynamicInstanceMethod(x: BarBar());
}
Third
If you need to use the class func syntax, as OP originally did:
class func doSomething()
You CANNOT simply use a protocol. Because protocol is not a class...
So compiler won't allow it.
But it's still possible, you can achieve that by using
Selector with NSObject.perform method
like this:
class ActualWork : NSObject{
func callDynamicClassMethod<T: NSObject>(x: T.Type, methodName: String){
x.perform(Selector(methodName));
}
}
class Ccc : NSObject{
#objc class func doSomething(){
print("Ccc class Doing something ");
}
}
class Ddd : NSObject{
#objc class func doSomething(){
print("Ccc class Doing something ");
}
#objc class func doOther(){
print("Ccc class Doing something ");
}
}
//This is how you can use it
func usage() {
let aw = ActualWork();
aw.callDynamicClassMethod(x: Ccc.self, methodName: "doSomething");
aw.callDynamicClassMethod(x: Ddd.self, methodName: "doSomething");
aw.callDynamicClassMethod(x: Ddd.self, methodName: "doOther");
}
Generics and Protocol oriented programming will do the job:
protocol Doable {
static func doSomething()
}
class Foo: Doable {
static func doSomething() {
debugPrint("Foo")
}
}
class Foobar: Doable {
static func doSomething() {
debugPrint("Foobar")
}
}
class ActualWork {
func callDynamicClassMethod<T: Doable>(x: T.Type) {
x.doSomething()
}
}
let work = ActualWork()
work.callDynamicClassMethod(x: Foo.self)
work.callDynamicClassMethod(x: Foobar.self)
you can achieve this with help of Protocol
protocol common {
static func doSomething()
}
class Foo : common{
static func doSomething() {
print("Foo")
}
}
class Foobar : common {
static func doSomething() {
print("Foobar")
}
}
class ActualWork{
//call following method with a variable type so that it accepts dynamic class name
func callDynamicClassMethod(x: common.Type) {
x.doSomething()
}
}
let fooObj : common = Foo()
let Foobarobj : common = Foobar()
let workObk = ActualWork()
workObk.callDynamicClassMethod(x:Foo.self)
workObk.callDynamicClassMethod(x:Foobar.self)
I think, there are three solutions. I shared an sample below.
Use "protocol" that has "doSomething()" function requirements.
Create a function which gets function definition as a parameter.
Use reflection. you can use EVReflection that is good Api for reflection.
sample code:
protocol FooProtocol {
static func doSomething()
}
class Foo: FooProtocol {
class func doSomething() {
print("Foo:doSomething")
}
}
class Foobar: FooProtocol {
class func doSomething() {
print("Foobar:doSomething")
}
}
class ActualWork {
func callDynamicClassMethod<T: FooProtocol>(x: T.Type) {
x.doSomething()
}
func callDynamicClassMethod(x: #autoclosure () -> Void) {
x()
}
func callDynamicClassMethod(x: () -> Void) {
x()
}
}
ActualWork().callDynamicClassMethod(x: Foo.self)
ActualWork().callDynamicClassMethod(x: Foobar.self)
print("\n")
ActualWork().callDynamicClassMethod(x: Foo.doSomething())
ActualWork().callDynamicClassMethod(x: Foobar.doSomething())
print("\n")
ActualWork().callDynamicClassMethod(x: Foo.doSomething)
ActualWork().callDynamicClassMethod(x: Foobar.doSomething)
Looks like you are searching for duck typing, and this is harder to achieve in a statically typed language (with some exceptions, listed in the linked Wikipedia page).
This is because dynamically calling a method requires knowledge about the layout of the target object, thus either inheritance of the class declaring the method, or conformance to a protocol that requires that method.
Starting with Swift 4.2, and the introduction of dynamic member lookup, there is another approach to solve your problem, however it also involves some ceremony:
// This needs to be used as base of all classes that you want to pass
// as arguments
#dynamicMemberLookup
class BaseDynamicClass {
subscript(dynamicMember member: String) -> () -> Void {
return { /* empty closure do nothing */ }
}
}
// subclasses can choose to respond to member queries any way they like
class Foo: BaseDynamicClass {
override subscript(dynamicMember member: String) -> () -> Void {
if member == "doSomething" { return doSomething }
return super[dynamicMember: member]
}
func doSomething() {
print("Dynamic from Foo")
}
}
class Bar: BaseDynamicClass {
override subscript(dynamicMember member: String) -> () -> Void {
if member == "doSomething" { return doSomething }
return super[dynamicMember: member]
}
func doSomething() {
print("Dynamic from Bar")
}
}
func test(receiver: BaseDynamicClass) {
receiver.doSomething()
}
test(receiver: Bar()) // Dynamic from Bar
To conclude, in the current Swift version there is no way to have both the argument and the method dynamic, some common ground needs to be set.

Swift dynamic type Debug/Release

I've this piece of code:
class NotificationsController: NSObject {
static var classNotifier: AnyClass {
if #available(iOS 10, *) {
return UNUserNotificationCenter.classForCoder()
} else {
return UILocalNotification.classForCoder()
}
}
static func foo() {
NotificationsController.classNotifier.foo()
}
}
Where:
protocol Notificable: class {
static func foo()
}
extension UNUserNotificationCenter: Notificable {
static func foo() {
// do something
}
}
extension UILocalNotification: Notificable {
static func foo() {
// do something
}
}
Building in Debug mode works fine.
When I build in Release mode (for archiving), compiler says that AnyClass have not a function called "foo".
Now, I know that if I remove Release optimizations build works, but I think would be the wrong solution.
Other solutions?
After some time I do investigation of the code and rewrite you're solution. Problem is connected with protocol Notificable and instance function func foo().
You try to call this function as class function not instance one and there is a problem.
Example of the working solution.
protocol Notificable: class {
static func foo()
}
extension UNUserNotificationCenter: Notificable {
internal static func foo() {
}
}
extension UILocalNotification: Notificable {
internal static func foo() {
}
}
class NotificationsController: NSObject {
static var classNotifier: AnyClass {
if #available(iOS 10, *) {
return UNUserNotificationCenter.classForCoder()
} else {
return UILocalNotification.classForCoder()
}
}
static func foo() {
classNotifier.foo()
}
}

How to Call same class in class function to instance functionin swift

i have one class in there are 2 methods first is class method and another is normal method and i want to called 2nd method call from class method, i have try many code but still i'm not getting solutions please guide me and help.
class ClassTest : NSObject
{
class func SentByUserString() -> String
{
// i want call here to sample method
return "hello"
}
func sample() -> Void
{
print("Sample Method Called")
}
}
You need to create static instance of that class and then call that method from that class function using that static instance. Change your code something like this
class ClassTest : NSObject {
struct Static {
static var instance: ClassTest?
}
class func sharedManager() -> ClassTest {
if (Static.instance == nil)
{
Static.instance = ClassTest()
}
return Static.instance!
}
class func SentByUserString() -> String {
// now call here your sample method like this
Static.instance?.sample()
return "hello"
}
func sample() -> Void {
print("Sample Method Called")
}
}
It's not really something you should be doing, but you can just make an instance of the class in that method, and call the sample method on that instance.
class func SentByUserString() -> String {
let temp = ClassTest()
temp.sample()
return "hello"
}

Swift - How can I override an extension method in a concrete subclass

I have an extension on UIView implementing a protocol
protocol SomeProtocol {
var property : Int
}
extension UIView : SomeProtocol {
var property : Int {
get {
return 0
}
set {
// do nothing
}
}
}
in a concrete subclass I want to override this extension method:
class Subclass : UIView, SomeProtocol {
var _property : Int = 1
var property : Int {
get { return _property}
set(val) {_property = val}
}
}
I set breakpoints and see that the extension method is called and not the concrete subclass method:
var subclassObject = Subclass()
someObject.doSomethingWithConcreteSubclassObject(subclassObject)
// other code;
fun doSomethingWithConcreteSuclassObject(object : UIView) {
var value = object.property // always goes to extension class get/set
}
As others have noted, Swift does not (yet) allow you to override a method declared in a class extension. However, I'm not sure whether you'll ever get the behavior you want even if/when Swift someday allows you to override these methods.
Consider how Swift deals with protocols and protocol extensions. Given a protocol to print some metasyntactic variable names:
protocol Metasyntactic {
func foo() -> String
func bar() -> String
}
An extension to provide default implementations:
extension Metasyntactic {
func foo() -> String {
return "foo"
}
func bar() -> String {
return "bar"
}
}
And a class that conforms to the protocol:
class FooBar : Metasyntactic {
func foo() -> String {
return "FOO"
}
func bar() -> String {
return "BAR"
}
}
Swift will use dynamic dispatch to call the appropriate implementations of foo() and bar() based on each variable's runtime type rather than on the type inferred by the compiler:
let a = FooBar()
a.foo() // Prints "FOO"
a.bar() // Prints "BAR"
let b: Metasyntactic = FooBar()
b.foo() // Prints "FOO"
b.bar() // Prints "BAR"
If, however, we extend the protocol further to add a new method:
extension Metasyntactic {
func baz() -> String {
return "baz"
}
}
And if we override our new method in a class that conforms to the protocol:
class FooBarBaz : Metasyntactic {
func foo() -> String {
return "FOO"
}
func bar() -> String {
return "BAR"
}
func baz() -> String {
return "BAZ"
}
}
Swift will now use static dispatch to call the appropriate implementation of baz() based on the type inferred by the compiler:
let a = FooBarBaz()
a.baz() // Prints "BAZ"
let b: Metasyntactic = FooBarBaz()
b.baz() // Prints "baz"
Alexandros Salazar has a fantastic blog post explaining this behavior in depth, but suffice it to say that Swift only uses dynamic dispatch for methods declared in the original protocol, not for methods declared in protocol extensions. I imagine the same would be true of class extensions, as well.
I know this question has been asked a while ago. But this will be handy for someone who looking for an easier way. There is a way of overriding an extension methods. I know its bit hacky but it does the job beautifully.
If you declare your protocol with #objc
#objc protocol MethodOverridable {
func overrideMe()
}
In Extension
extension MainClass: MethodOverridable {
func overrideMe() {
print("Something useful")
}
}
Subclass - You can able to override it in your subclass. It works like a magic. Well, not really when adding #objc it exposes your protocol to Objective-C and its Runtime. That allows your subclass to override.
class SubClass: MainClass {
override func overrideMe() {
print("Something more useful")
}
}
Swift 5
class Class
{
#objc dynamic func make() { print("make from class") }
}
class SubClass: Class {}
extension SubClass {
override func make() {
print("override")
}
}
It looks like you can override property for 2nd super class property. For example, you can access UIView property by making extension to the UILabel wanting to override frame property of UIView. This sample works for me in Xcode 6.3.2
extension UILabel {
override public var frame: CGRect {
didSet {
println("\(frame)")
}
}
}
You can't do this through normal means.
It's in Apple's docs that you can't override a method in an extension in a subclass.
Also, extensions can add new functionality to a type, but they cannot override existing functionality.
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
I think you forgot to override the superclass property in your subclass:
class Subclass : UIView {
var _property : Int = 1
override var property : Int {
get { return _property}
set(val) {_property = val}
}
}

Resources